﻿/**
 * @file setting_wlan.c
 * set wifi from setting ui of watch
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_watch.h"

#if USE_LV_WLAN != 0

#if WLAN_MANUAL_SET_WIFI_SUPP != 0

/*********************
 *      DEFINES
 *********************/
#define WLAN_DEF_FONT               (LV_THEME_WATCH_NIGHT_FONT_NORMAL)

#define WLAN_STYLE_FONT             (&lv_watch_font20)
#define WLAN_STYLE_FONT_GRAY        (&lv_watch_font20_gray)
#define WLAN_STYLE_FONT_BLACK       (&lv_watch_font20_black)
#define WLAN_STYLE_FONT_SMALL       (&lv_watch_font20)
#define WLAN_STYLE_FONT_SMALL_BLACK (&lv_watch_font20_black)
#define WLAN_STYLE_FONT_SMALL_GRAY  (&lv_watch_font20_gray)

/**********************
 *      TYPEDEFS
 **********************/
typedef struct {
    lv_watch_obj_ext_t oldext;
    lv_obj_t * note_label;
    lv_obj_t * list;
    lv_obj_t * sw;
    lv_obj_t * sw_label;
    lv_obj_t * refresh_img;
    lv_style_t btn_style;
} wlan_ext_t;

typedef struct {
    lv_watch_obj_ext_t oldext;
    hal_wlan_ap_t ap;
    lv_obj_t * pwd_label;
    lv_obj_t * connect_btn;
    lv_obj_t * cancel_btn;
    char * pwd;
} wlan_login_ext_t;

typedef struct {
    lv_watch_obj_ext_t oldext;
    lv_obj_t * list;
} wlan_saved_nw_ext_t;

typedef struct {
    lv_watch_obj_ext_t oldext;
    hal_wlan_ap_t ap;
} wlan_act_ap_ext_t;

typedef struct {
    lv_watch_obj_ext_t oldext;
    hal_wlan_ap_t ap;
} wlan_saved_ap_ext_t;

typedef struct {
    lv_watch_obj_ext_t oldext;
    lv_obj_t * ssid_label;
    lv_obj_t * pwd_label;
    lv_obj_t * security_txt_label;
    lv_obj_t * ok_btn;
    lv_obj_t * cancel_btn;
    char * ssid;
    char * pwd;
} wlan_add_nw_ext_t;

enum {
    WLAN_BTN_TYPE_ACT = 0,
    WLAN_BTN_TYPE_NO_INTERNET,
    WLAN_BTN_TYPE_OPENING,
    WLAN_BTN_TYPE_GETTING_IP,
    WLAN_BTN_TYPE_SAVED,
    WLAN_BTN_TYPE_OPEN_FAIL,
    WLAN_BTN_TYPE_PASSWORD_ERROR,
    WLAN_BTN_TYPE_SCAN_LIST,
    WLAN_BTN_TYPE_REFRESH,
    WLAN_BTN_TYPE_REFRESHING, // play animation for refreshing
};
typedef uint8_t WLAN_BTN_TYPE_T;

typedef bool (*WLAN_DIALOG_OK_BTN_EVENT_CB)(lv_obj_t * btn);

/**********************
 *  STATIC PROTOTYPES
 **********************/
static void wlan_event_cb(HAL_WLAN_EVENT_T event);
static void * wlan_get_ext(lv_watch_Activity_Id_t actId);
static void wlan_add_note_label(lv_obj_t ** note_label, lv_obj_t * par, uint16_t txt_id);
static lv_obj_t * wlan_create(lv_obj_t * activity_obj);

/**********************
 *  STATIC VARIABLES
 **********************/

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
***********************/
void wlan_init(void)
{
    hal_wlan_init(false, watch_get_lcd_status, wlan_event_cb);
}

void wlan_create_btn_action(lv_obj_t * btn, lv_event_t e)
{
    (void)btn;

    if(LV_EVENT_CLICKED != e) return;

    lv_watch_png_cache_all_free();
    lv_obj_t * obj = wlan_create(NULL);
    LV_ASSERT_MEM(obj);
}

/**********************
 *   STATIC FUNCTIONS
 **********************/
static void * wlan_get_ext(lv_watch_Activity_Id_t actId)
{
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(actId);
    if(NULL == activity_obj) return NULL;

    lv_obj_t * obj = NULL;
    lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &obj);
    if(NULL == obj) return NULL;

    return lv_obj_get_ext_attr(obj);
}

static lv_obj_t * wlan_add_title(lv_obj_t * par, uint32_t txt_id)
{
    lv_obj_t * cont = lv_cont_create(par, NULL);
    lv_obj_add_style(cont, LV_CONT_PART_MAIN, &lv_watch_style_transp);
    lv_obj_set_click(cont, false);
    lv_cont_set_fit(cont, LV_FIT_TIGHT);

    lv_obj_t * title_label = lv_label_create(cont, NULL);
    lv_obj_add_style(title_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_SMALL_GRAY);
    lv_label_set_align(title_label, LV_LABEL_ALIGN_CENTER);
    lv_label_set_long_mode(title_label, LV_LABEL_LONG_SROLL_CIRC);
    lv_obj_set_width(title_label, lv_obj_get_width_fit(par));
    lv_label_set_text_id(title_label, txt_id);

    lv_obj_align(cont, par, LV_ALIGN_IN_TOP_MID, 0,
                 lv_obj_get_style_pad_top(par, LV_CONT_PART_MAIN));

    return cont;
}

static lv_obj_t * wlan_add_bg(lv_obj_t * par)
{
    lv_obj_t * cont = lv_cont_create(par, NULL);
    lv_obj_set_style_local_bg_color(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
    lv_obj_set_style_local_pad_top(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10);
    lv_obj_set_style_local_pad_bottom(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10);
    lv_obj_set_style_local_pad_left(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10);
    lv_obj_set_style_local_pad_right(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10);
    lv_obj_set_size(cont, lv_obj_get_width(par), lv_obj_get_height(par));
    lv_obj_align(cont, par, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_click(cont, false);
    return cont;
}

static void wlan_list_set_common_param(lv_obj_t * list)
{
    lv_obj_add_style(list, LV_LIST_PART_BG, &lv_style_transp_tight);
    lv_obj_add_style(list, LV_LIST_PART_SCROLLABLE, &lv_style_transp_tight);
    lv_obj_set_style_local_pad_inner(list, LV_LIST_PART_SCROLLABLE, LV_STATE_DEFAULT, 4);
    lv_obj_set_style_local_pad_left(list, LV_LIST_PART_SCROLLBAR, LV_STATE_DEFAULT, 0);
    lv_obj_set_style_local_pad_right(list, LV_LIST_PART_SCROLLBAR, LV_STATE_DEFAULT, -4);
    lv_obj_set_style_local_pad_top(list, LV_LIST_PART_SCROLLBAR, LV_STATE_DEFAULT, 1);
    lv_obj_set_style_local_pad_bottom(list, LV_LIST_PART_SCROLLBAR, LV_STATE_DEFAULT, 1);
    lv_obj_set_style_local_bg_color(list, LV_LIST_PART_SCROLLBAR, LV_STATE_DEFAULT,
                                    LV_COLOR_GRAY);

    lv_list_set_scrollbar_mode(list, LV_SCROLLBAR_MODE_OFF);
    lv_page_set_scrl_layout(list, LV_LAYOUT_COLUMN_MID);

    lv_watch_obj_add_element(list);
    lv_watch_obj_add_element(lv_page_get_scrollable(list));
}

static void wlan_list_set_common_param_with_shadow(lv_obj_t * list)
{
    wlan_list_set_common_param(list);

    lv_obj_set_style_local_shadow_width(list, LV_LIST_PART_BG, LV_STATE_DEFAULT, 2);
    lv_obj_set_style_local_shadow_opa(list, LV_LIST_PART_BG, LV_STATE_DEFAULT, LV_OPA_COVER);
    lv_obj_set_style_local_shadow_color(list, LV_LIST_PART_BG, LV_STATE_DEFAULT, LV_COLOR_GRAY);
    lv_obj_set_style_local_pad_left(list, LV_LIST_PART_BG, LV_STATE_DEFAULT, 4);
    lv_obj_set_style_local_pad_right(list, LV_LIST_PART_BG, LV_STATE_DEFAULT, 4);
}

static void wlan_del_ui(lv_watch_Activity_Id_t act_id)
{
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(act_id);
    if(NULL == activity_obj) return;

    lv_watch_activity_ext_t * ext = lv_obj_get_ext_attr(activity_obj);
    LV_ASSERT_MEM(ext);
    if(ext->prepare_destory) {
        ext->prepare_destory(activity_obj);
    }
    lv_obj_del(activity_obj);
}

static void wlan_btn_set_normal_style(lv_obj_t * btn)
{
    lv_obj_clean_style_list(btn, LV_BTN_PART_MAIN);
    lv_obj_add_style(btn, LV_BTN_PART_MAIN, &lv_style_pretty);
    lv_obj_set_style_local_bg_opa(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_40);
    lv_obj_set_style_local_bg_color(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
    lv_obj_set_style_local_bg_opa(btn, LV_BTN_PART_MAIN, LV_STATE_PRESSED, LV_OPA_COVER);
}

static void wlan_refreshing_anim(lv_anim_t * a)
{
    lv_obj_t * img = (lv_obj_t *)a->var;
    uint8_t step = lv_watch_get_free_num(img);
    if(1 == step) {
        lv_img_set_src(img, ICON_SETTING_REFRESH_2);
        lv_watch_set_free_num(img, 2);
    } else if(2 == step) {
        lv_img_set_src(img, ICON_SETTING_REFRESH_1);
        lv_watch_set_free_num(img, 1);
    } else {
        printf("%s: warning, wrong step %d\n", __FUNCTION__, step);
    }
}

static void wlan_play_refreshing_anim(lv_obj_t * img)
{
    printf("%s\n", __FUNCTION__);

    lv_img_set_src(img, ICON_SETTING_REFRESH_2);
    lv_watch_set_free_num(img, 2);
    lv_anim_t a = {};
    lv_anim_init(&a);
    lv_anim_set_var(&a, img);
    lv_anim_set_start_cb(&a, (lv_anim_ready_cb_t)wlan_refreshing_anim);
    lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
    lv_anim_set_time(&a, 150);
    lv_anim_start(&a);
}

static const void * wlan_get_signal_src(HAL_WLAN_SIGNAL_STRENGTH_T rssi_level)
{
    switch(rssi_level) {
    case HAL_WLAN_SIGNAL_STRENGTH_EXCELLENT:
        return ICON_SETTING_WIFI_FULL;
    case HAL_WLAN_SIGNAL_STRENGTH_GOOD:
        return ICON_SETTING_WIFI_HIGH;
    case HAL_WLAN_SIGNAL_STRENGTH_FAIR:
        return ICON_SETTING_WIFI_MID;
    case HAL_WLAN_SIGNAL_STRENGTH_POOR:
        return ICON_SETTING_WIFI_LOW;
    default:
        printf("%s: warning, invalid level %d\n", __FUNCTION__, rssi_level);
        return ICON_SETTING_WIFI_LOW;
    }
}

static void wlan_get_signal_txt(int8_t power, uint8_t txt_len, char * txt)
{
    if((NULL == txt) || (0 == txt_len)) {
        printf("%s: warning, txt is NULL\n", __FUNCTION__);
        return;
    }

    HAL_WLAN_SIGNAL_STRENGTH_T rssi_level = hal_wlan_rssi_level_calc(power);
    switch(rssi_level) {
    case HAL_WLAN_SIGNAL_STRENGTH_EXCELLENT:
        strncpy(txt, lv_lang_get_text(WATCH_TEXT_ID_EXCELLENT), txt_len);
        break;
    case HAL_WLAN_SIGNAL_STRENGTH_GOOD:
        strncpy(txt, lv_lang_get_text(WATCH_TEXT_ID_GOOD), txt_len);
        break;
    case HAL_WLAN_SIGNAL_STRENGTH_FAIR:
        strncpy(txt, lv_lang_get_text(WATCH_TEXT_ID_FAIR), txt_len);
        break;
    case HAL_WLAN_SIGNAL_STRENGTH_POOR:
        strncpy(txt, lv_lang_get_text(WATCH_TEXT_ID_POOR), txt_len);
        break;
    default:
        printf("%s: warning, invalid signal %d\n", __FUNCTION__, power);
        strncpy(txt, lv_lang_get_text(WATCH_TEXT_ID_POOR), txt_len);
        break;
    }
}

static bool wlan_check_pwd_len(HAL_WLAN_SECURITY_T security, char * pwd)
{
    bool ret = false;
    uint8_t pwd_len = 0;
    if(pwd) {
        pwd_len = strlen(pwd);
    }
    if(hal_wlan_get_min_pwd_len(security) <= pwd_len) {
        ret = true;
    }

    return ret;
}

static void wlan_get_security_txt(HAL_WLAN_SECURITY_T security, uint8_t txt_len, char * txt)
{
    if((NULL == txt) || (0 == txt_len)) {
        printf("%s: warning, txt is NULL\n", __FUNCTION__);
        return;
    }

    Hal_Mem_Set(txt, 0, txt_len);
    switch(security) {
    case HAL_WLAN_SECURITY_OPEN:
        strncpy(txt, lv_lang_get_text(WATCH_TEXT_ID_SECURITY_NONE), txt_len);
        break;
    case HAL_WLAN_SECURITY_WEP:
        strncpy(txt, "WEP", txt_len);
        break;
    case HAL_WLAN_SECURITY_WPA:
        strncpy(txt, "WPA", txt_len);
        break;
    case HAL_WLAN_SECURITY_WPA2:
        strncpy(txt, "WPA2", txt_len);
        break;
    case HAL_WLAN_SECURITY_WPA_WPA2:
        strncpy(txt, "WPA/WPA2", txt_len);
        break;
    default:
        printf("%s: warning, unsupported security %d\n", __FUNCTION__, security);
        strncpy(txt, lv_lang_get_text(WATCH_TEXT_ID_UNSUPPORTED), txt_len);
        break;
    }
}

static void wlan_login_prepare_destory(lv_obj_t * activity_obj)
{
    printf("%s\n", __FUNCTION__);

    wlan_login_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_LOGIN);
    if(NULL == ext) {
        printf("%s: error, ui lost!\n", __FUNCTION__);
        return;
    }

    if(ext->pwd) {
        Hal_Mem_Free(ext->pwd);
    }

    lv_watch_png_cache_all_free();
}

static void wlan_rm_ap_list_btn(wlan_ext_t * ext)
{
    printf("%s\n", __FUNCTION__);
    lv_obj_t * scrl = lv_page_get_scrl(ext->list);
    lv_obj_t * btn = _lv_ll_get_prev(&scrl->child_ll, lv_obj_get_parent(ext->sw));
    while(btn) {
        lv_obj_t * btn_prev = _lv_ll_get_prev(&scrl->child_ll, btn);
        void * ptr = lv_watch_get_free_ptr(lv_obj_get_child_back(btn, NULL));
        if(ptr) {
            Hal_Mem_Free(ptr);
        }
        lv_obj_del(btn);
        btn = btn_prev;
    }
    ext->refresh_img = NULL;
}

#if USE_LV_WATCH_KEYPAD != 0
static void wlan_btn_set_input_style(lv_obj_t * btn)
{
    lv_obj_add_style(btn, LV_BTN_PART_MAIN, &lv_style_pretty);
    lv_obj_set_style_local_bg_color(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
    lv_obj_set_style_local_bg_grad_color(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
    lv_obj_set_style_local_pad_top(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 5);
    lv_obj_set_style_local_pad_bottom(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 5);
    lv_obj_set_style_local_pad_left(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 5);
    lv_obj_set_style_local_pad_right(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 5);
}

static void wlan_login_connect_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_login_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_LOGIN);
    if(NULL == ext) return;

    printf("%s: pwd %s\n", __FUNCTION__, ext->pwd);
    if(wlan_check_pwd_len(ext->ap.security, ext->pwd)) {
        hal_wlan_ui_open_ap(ext->ap.ssid, ext->ap.security, ext->pwd);

        wlan_del_ui(ACT_ID_WLAN_LOGIN);
    }
}

static void wlan_get_pwd_handle(char * text, char * ssid, HAL_WLAN_SECURITY_T security,
                                char ** pwd, lv_obj_t * pwd_label, lv_obj_t * btn)
{
    uint8_t len = 0;
    if(text) {
        len = strlen(text);
    }
    if((0 == len) && (*pwd)) {
        if(ssid && (hal_wlan_get_min_pwd_len(security) <= strlen(*pwd))) {
            lv_obj_set_style_local_text_color(lv_obj_get_child(btn, NULL),
                                              LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
        }
        Hal_Mem_Free(*pwd);
        *pwd = NULL;

        lv_obj_add_style(pwd_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_GRAY);
        lv_label_set_text_id(pwd_label, WATCH_TEXT_ID_PASSWORD);
    } else if(0 < len) {
        if(NULL == *pwd) {
            lv_obj_add_style(pwd_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_BLACK);
        } else if(0 == strcmp(*pwd, text)) {
            Hal_Mem_Free(text);
            return;
        } else {
            Hal_Mem_Free(*pwd);
        }
        *pwd = text;

        if(ssid && (hal_wlan_get_min_pwd_len(security) <= len)) {
            lv_obj_set_style_local_text_color(lv_obj_get_child(btn, NULL),
                                              LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
        }

        char temp_pwd[64 + 1] = {};
        for(uint8_t i = 0;i < len;i++) {
            temp_pwd[i] = '*';
        }
        lv_label_set_text(pwd_label, temp_pwd);
    }
}

static void wlan_login_get_pwd(char * text)
{
    wlan_login_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_LOGIN);
    if(NULL == ext) return;

    wlan_get_pwd_handle(text, ext->ap.ssid, ext->ap.security, &ext->pwd,
                        ext->pwd_label, ext->connect_btn);
}

static void wlan_login_pwd_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_login_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_LOGIN);
    if(NULL == ext) return;

    keypad_para_t param;
    param.text = ext->pwd;
    param.password_mode = true;
    param.max_length = HAL_WLAN_MAX_PWD_LEN;
    param.min_length = hal_wlan_get_min_pwd_len(ext->ap.security);
    param.func = wlan_login_get_pwd;
    keypad_create_btn_action(&param);
}
#endif

static lv_obj_t * wlan_add_ap_info(lv_obj_t * list, hal_wlan_ap_t * ap)
{
    lv_obj_t * detail_cont = lv_cont_create(list, NULL);
    lv_obj_set_click(detail_cont, false);
    lv_obj_set_style_local_bg_opa(detail_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0);
    lv_obj_set_style_local_shadow_opa(detail_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
    lv_obj_set_style_local_shadow_width(detail_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 2);
    lv_obj_set_style_local_shadow_color(detail_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT,
                                        LV_COLOR_GRAY);
    lv_obj_set_style_local_pad_inner(detail_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 4);
    lv_obj_set_style_local_pad_top(detail_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 2);
    lv_obj_set_style_local_pad_bottom(detail_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 2);
    lv_obj_set_style_local_pad_left(detail_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 2);
    lv_obj_set_style_local_pad_right(detail_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 2);
    lv_cont_set_fit2(detail_cont, LV_FIT_PARENT, LV_FIT_TIGHT);
    lv_cont_set_layout(detail_cont, LV_LAYOUT_COLUMN_MID);

    lv_obj_t * security_label = lv_label_create(detail_cont, NULL);
    lv_obj_add_style(security_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_SMALL);
    lv_label_set_long_mode(security_label, LV_LABEL_LONG_BREAK);
    lv_obj_set_width(security_label, lv_obj_get_width_fit(detail_cont));
    lv_label_set_text_id(security_label, WATCH_TEXT_ID_SECURITY);
    lv_label_ins_text(security_label, LV_LABEL_POS_LAST, "\n");
    char security_txt[20] = {};
    wlan_get_security_txt(ap->security, 20, security_txt);
    lv_label_ins_text(security_label, LV_LABEL_POS_LAST, security_txt);

    lv_obj_t * signal_label = lv_label_create(detail_cont, security_label);
    lv_label_set_text_id(signal_label, WATCH_TEXT_ID_SIGNAL_STRENGTH);
    char signal_txt[20] = {};
    wlan_get_signal_txt(ap->power, 20, signal_txt);
    lv_label_ins_text(signal_label, LV_LABEL_POS_LAST, signal_txt);

    return detail_cont;
}

static void wlan_login_create(hal_wlan_ap_t * ap)
{
    lv_watch_activity_ext_t activity_ext;
    memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
    activity_ext.actId = ACT_ID_WLAN_LOGIN;
    activity_ext.create = NULL;
    activity_ext.prepare_destory = wlan_login_prepare_destory;
    lv_obj_t * activity_obj = lv_watch_creat_activity_obj(&activity_ext);
    LV_ASSERT_MEM(activity_obj);

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    wlan_login_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(wlan_login_ext_t));
    LV_ASSERT_MEM(ext);

    ext->pwd = NULL;
    Hal_Mem_Copy(&ext->ap, ap, sizeof(hal_wlan_ap_t));
    printf("%s: ap %s\n", __FUNCTION__, ap->ssid);

    lv_obj_t * cont = wlan_add_bg(obj);

    lv_coord_t pad_top = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN);
    lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(cont, LV_CONT_PART_MAIN);

    lv_obj_t * title_label = lv_label_create(cont, NULL);
    lv_obj_add_style(title_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    lv_label_set_align(title_label, LV_LABEL_ALIGN_CENTER);
    lv_label_set_long_mode(title_label, LV_LABEL_LONG_SROLL_CIRC);
    lv_obj_set_width(title_label, lv_obj_get_width_fit(cont) - 20);
    lv_label_set_text(title_label, ap->ssid);
    lv_obj_align(title_label, cont, LV_ALIGN_IN_TOP_MID, 0, pad_top);

    lv_obj_t * list = lv_list_create(cont, NULL);
    wlan_list_set_common_param(list);
    lv_obj_set_size(list, lv_obj_get_width_fit(cont),
                    lv_obj_get_height(cont) - lv_obj_get_y(title_label)-
                    lv_obj_get_height(title_label) - 2 - pad_bottom);
    lv_obj_align(list, cont, LV_ALIGN_IN_BOTTOM_MID, 0, -pad_bottom);

    wlan_add_ap_info(list, ap);

#if USE_LV_WATCH_KEYPAD != 0
    if((HAL_WLAN_SECURITY_OPEN != ap->security)
       && (HAL_WLAN_SECURITY_MAX > ap->security)) {
        lv_obj_t * pwd_btn = lv_btn_create(list, NULL);
        lv_page_glue_obj(pwd_btn, true);
        lv_obj_set_size(pwd_btn, lv_obj_get_width_fit(list), lv_obj_get_height(title_label) + 10);
        wlan_btn_set_input_style(pwd_btn);
        lv_obj_set_event_cb(pwd_btn, wlan_login_pwd_btn_event_cb);
        lv_watch_obj_add_element(pwd_btn);

        ext->pwd_label = lv_label_create(pwd_btn, NULL);
        lv_obj_add_style(ext->pwd_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_GRAY);
        lv_label_set_long_mode(ext->pwd_label, LV_LABEL_LONG_SROLL_CIRC);
        lv_obj_set_width(ext->pwd_label, lv_obj_get_width(pwd_btn) - 10);
        lv_label_set_text_id(ext->pwd_label, WATCH_TEXT_ID_PASSWORD);
        lv_obj_align(ext->pwd_label, pwd_btn, LV_ALIGN_CENTER, 0, 0);
    }
#endif

#if USE_LV_WATCH_KEYPAD != 0
    ext->connect_btn = lv_btn_create(list, NULL);
    wlan_btn_set_normal_style(ext->connect_btn);
    lv_page_glue_obj(ext->connect_btn, true);
    lv_obj_set_size(ext->connect_btn, lv_obj_get_width_fit(list), lv_obj_get_height(title_label) + 10);
    if(HAL_WLAN_SECURITY_MAX == ap->security) {
        lv_obj_set_click(ext->connect_btn, false);
    } else {
        lv_obj_set_event_cb(ext->connect_btn, wlan_login_connect_btn_event_cb);
    }
    lv_watch_obj_add_element(ext->connect_btn);

    lv_obj_t * connect_label = lv_label_create(ext->connect_btn, NULL);
    lv_obj_add_style(connect_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    if(HAL_WLAN_SECURITY_OPEN != ap->security) {
        lv_obj_set_style_local_text_color(connect_label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT,
                                          LV_COLOR_GRAY);
    }
    if(HAL_WLAN_SECURITY_MAX == ap->security) {
        lv_label_set_text_id(connect_label, WATCH_TEXT_ID_NOT_CONNECT);
    } else {
        lv_label_set_text_id(connect_label, WATCH_TEXT_ID_CONNECT);
    }
    lv_obj_align(connect_label, ext->connect_btn, LV_ALIGN_CENTER, 0, 0);
#endif
}

static void wlan_del_saved_nw_ok_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    lv_obj_t * label = lv_obj_get_child(btn, NULL);
    lv_obj_t * saved_nw_btn = (lv_obj_t *)lv_watch_get_free_ptr(label);
    lv_obj_t * saved_nw_label = lv_obj_get_child(saved_nw_btn, NULL);
    hal_wlan_nw_t * saved_nw = (hal_wlan_nw_t *)lv_watch_get_free_ptr(saved_nw_label);

    lv_obj_t * scrl = lv_obj_get_parent(saved_nw_btn);
    lv_obj_del(saved_nw_btn);
    if(NULL == _lv_ll_get_head(&scrl->child_ll)) {
        lv_obj_t * cont = lv_obj_get_parent(lv_obj_get_parent(scrl));
        lv_obj_t * empty_label = lv_label_create(cont, NULL);
        lv_obj_add_style(empty_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
        lv_label_set_text_id(empty_label, WATCH_TEXT_ID_EMPTY);
        lv_obj_align(empty_label, cont, LV_ALIGN_CENTER, 0, -20);
    }

    hal_wlan_ui_del_saved_nw(saved_nw->ssid, saved_nw->security);

    wlan_del_ui(ACT_ID_WLAN_DEL_SAVED_NW);
}

static void wlan_del_saved_nw_cancel_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_del_ui(ACT_ID_WLAN_DEL_SAVED_NW);
}

static void wlan_del_saved_nw_create(lv_obj_t * saved_ap_btn)
{
    lv_watch_activity_ext_t activity_ext;
    memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
    activity_ext.actId = ACT_ID_WLAN_DEL_SAVED_NW;
    activity_ext.create = NULL;
    activity_ext.prepare_destory = NULL;
    lv_obj_t * activity_obj = lv_watch_creat_activity_obj(&activity_ext);
    LV_ASSERT_MEM(activity_obj);

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);

    lv_obj_t * saved_ap_label = lv_obj_get_child(saved_ap_btn, NULL);
    hal_wlan_nw_t * ap = (hal_wlan_nw_t *)lv_watch_get_free_ptr(saved_ap_label);
    printf("%s: ap ssid %s\n", __FUNCTION__, ap->ssid);

    lv_obj_t * cont = wlan_add_bg(obj);

    lv_bidi_dir_t dir = lv_obj_get_base_dir(cont);
    lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(cont, LV_CONT_PART_MAIN);

    lv_obj_t * title_cont = wlan_add_title(cont, WATCH_TEXT_ID_DEL_NW);

    lv_obj_t * ok_btn = lv_btn_create(cont, NULL);
    lv_obj_add_style(ok_btn, LV_BTN_PART_MAIN, &lv_style_pretty);
    lv_obj_set_style_local_bg_opa(ok_btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_40);
    lv_obj_set_style_local_bg_color(ok_btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
    lv_obj_set_style_local_bg_opa(ok_btn, LV_BTN_PART_MAIN, LV_STATE_PRESSED, LV_OPA_COVER);
    lv_obj_set_size(ok_btn, 100, lv_obj_get_height(title_cont) + 4);
    lv_obj_set_event_cb(ok_btn, wlan_del_saved_nw_ok_btn_event_cb);
    lv_watch_obj_add_element(ok_btn);

    lv_obj_t * ok_label = lv_label_create(ok_btn, NULL);
    lv_obj_add_style(ok_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    lv_label_set_text_id(ok_label, WATCH_TEXT_ID_OK);
    lv_watch_set_free_ptr(ok_label, saved_ap_btn);
    lv_obj_align(ok_label, ok_btn, LV_ALIGN_CENTER, 0, 0);

    lv_obj_t * cancel_btn = lv_btn_create(cont, ok_btn);
    lv_obj_set_event_cb(cancel_btn, wlan_del_saved_nw_cancel_btn_event_cb);
    lv_watch_obj_add_element(cancel_btn);

    lv_obj_t * cancel_label = lv_label_create(cancel_btn, NULL);
    lv_obj_add_style(cancel_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    lv_label_set_text_id(cancel_label, WATCH_TEXT_ID_CANCEL);
    lv_obj_align(cancel_label, cancel_btn, LV_ALIGN_CENTER, 0, 0);

    if(LV_BIDI_DIR_RTL == dir) {
        lv_obj_align(cancel_btn, cont, LV_ALIGN_IN_BOTTOM_RIGHT, -10, -pad_bottom);
        lv_obj_align(ok_btn, cont, LV_ALIGN_IN_BOTTOM_LEFT, 10, -pad_bottom);
    } else {
        lv_obj_align(ok_btn, cont, LV_ALIGN_IN_BOTTOM_RIGHT, -10, -pad_bottom);
        lv_obj_align(cancel_btn, cont, LV_ALIGN_IN_BOTTOM_LEFT, 10, -pad_bottom);
    }

    lv_obj_t * list = lv_list_create(cont, NULL);
    lv_obj_set_size(list, lv_obj_get_width_fit(cont),
                    lv_obj_get_y(ok_btn) - lv_obj_get_y(title_cont)
                    - lv_obj_get_height(title_cont) - 8);
    wlan_list_set_common_param_with_shadow(list);
    lv_obj_align(list, title_cont, LV_ALIGN_OUT_BOTTOM_MID, 0, 3);

    lv_obj_t * ssid_label = lv_label_create(list, NULL);
    lv_obj_add_style(ssid_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    lv_label_set_long_mode(ssid_label, LV_LABEL_LONG_BREAK);
    lv_obj_set_width(ssid_label, lv_obj_get_width_fit(list));
    lv_label_set_text_id(ssid_label, WATCH_TEXT_ID_SSID);
    lv_label_ins_text(ssid_label, LV_LABEL_POS_LAST, ":\n");
    lv_label_ins_text(ssid_label, LV_LABEL_POS_LAST, ap->ssid);

    lv_obj_t * security_label = lv_label_create(list, ssid_label);
    lv_label_set_text_id(security_label, WATCH_TEXT_ID_SECURITY);
    lv_label_ins_text(security_label, LV_LABEL_POS_LAST, "\n");
    char security_txt[20] = {};
    wlan_get_security_txt(ap->security, 20, security_txt);
    lv_label_ins_text(security_label, LV_LABEL_POS_LAST, security_txt);
    lv_obj_align(security_label, ssid_label, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
}

static void wlan_saved_nw_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_del_saved_nw_create(btn);
}

static void wlan_saved_nw_add_btn(lv_obj_t * list, lv_style_t * btn_style, hal_wlan_nw_t * ap)
{
    lv_obj_t * btn = lv_btn_create(list, NULL);
    lv_obj_add_style(btn, LV_BTN_PART_MAIN, btn_style);
    lv_btn_set_fit2(btn, LV_FIT_NONE, LV_FIT_TIGHT);
    lv_obj_set_width(btn, lv_obj_get_width(list));
    lv_btn_set_layout(btn, LV_LAYOUT_CENTER);
    lv_obj_set_event_cb(btn, wlan_saved_nw_btn_event_cb);
    lv_page_glue_obj(btn, true);
    lv_watch_obj_add_element(btn);

    lv_obj_t * label = lv_label_create(btn, NULL);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    lv_label_set_long_mode(label, LV_LABEL_LONG_SROLL_CIRC);
    lv_obj_set_width(label, lv_obj_get_width(btn) - 10);
    lv_label_set_text(label, ap->ssid);
    lv_watch_set_free_ptr(label, ap);
}

static void wlan_saved_nw_prepare_destory(lv_obj_t * activity_obj)
{
    printf("%s\n", __FUNCTION__);
}

static void wlan_saved_nw_create(void)
{
    lv_watch_activity_ext_t activity_ext;
    memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
    activity_ext.actId = ACT_ID_WLAN_SAVED_NW;
    activity_ext.create = NULL;
    activity_ext.prepare_destory = wlan_saved_nw_prepare_destory;
    lv_obj_t * activity_obj = lv_watch_creat_activity_obj(&activity_ext);
    LV_ASSERT_MEM(activity_obj);

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    wlan_saved_nw_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(wlan_saved_nw_ext_t));
    LV_ASSERT_MEM(ext);

    wlan_ext_t * wlan_ext = wlan_get_ext(ACT_ID_WLAN);
    LV_ASSERT_MEM(wlan_ext);

    lv_obj_t * cont = wlan_add_bg(obj);

    lv_obj_t * title_cont = wlan_add_title(cont, WATCH_TEXT_ID_SAVED_NW);

    lv_ll_t * nw_list = hal_wlan_get_nw_list();
    if(NULL == nw_list) {
        printf("%s: warning, nw_list is NULL\n", __FUNCTION__);
        return;
    }

    ext->list = NULL;
    hal_wlan_nw_t * node = _lv_ll_get_head(nw_list);
    hal_wlan_info_t * info = hal_wlan_get_info();
    while(node) {
        if(info
           && info->proc.ap
           && !info->proc.ap->is_hidden
           && (node == info->proc.ap->nw)
           && (HAL_WLAN_AP_STATE_OPENING == info->proc.proc_state)
           && info->proc.is_first) {
            printf("%s: not display the first opening ap\n", __FUNCTION__);
            node = _lv_ll_get_next(nw_list, node);
            continue;
        }

        if(NULL == ext->list) {
            ext->list = lv_list_create(cont, NULL);
            wlan_list_set_common_param(ext->list);
            lv_coord_t list_h = lv_obj_get_height(cont) - lv_obj_get_height(title_cont) - 12;
            lv_obj_set_size(ext->list, lv_obj_get_width_fit(cont), list_h);
            lv_obj_align(ext->list, cont, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
        }
        wlan_saved_nw_add_btn(ext->list, &wlan_ext->btn_style, node);
        node = _lv_ll_get_next(nw_list, node);
    }
    if(NULL == ext->list) {
        lv_obj_t * empty_label = lv_label_create(cont, NULL);
        lv_obj_add_style(empty_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
        lv_label_set_text_id(empty_label, WATCH_TEXT_ID_EMPTY);
        lv_obj_align(empty_label, cont, LV_ALIGN_CENTER, 0, -20);
    }
}

#if USE_LV_WATCH_KEYPAD != 0
static void wlan_add_nw_ok_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_add_nw_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_ADD_NW);
    if(NULL == ext) return;

    if(NULL == ext->ssid) {
        return;
    }

    hal_wlan_nw_t nw = {};
    nw.security = lv_watch_get_free_num(lv_obj_get_parent(ext->security_txt_label));
    printf("%s: sec %d, ssid %s, pwd %s\n", __FUNCTION__, nw.security, ext->ssid, ext->pwd);
    if(wlan_check_pwd_len(nw.security, ext->pwd)) {
        strncpy(nw.ssid, ext->ssid, HAL_WLAN_MAX_SSID_LEN + 1);
        if(ext->pwd) {
            strncpy(nw.pwd, ext->pwd, HAL_WLAN_MAX_PWD_LEN + 1);
        }
        hal_wlan_ui_add_nw(&nw);

        wlan_del_ui(ACT_ID_WLAN_ADD_NW);
        wlan_del_ui(ACT_ID_WLAN_OPTION);
    }
}

static void wlan_add_nw_get_ssid(char * text)
{
    wlan_add_nw_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_ADD_NW);
    if(NULL == ext) return;

    uint8_t len = 0;
    if(text) {
        len = strlen(text);
    }
    if((0 == len) && ext->ssid) {
        lv_obj_add_style(ext->ssid_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_GRAY);
        lv_label_set_text_id(ext->ssid_label, WATCH_TEXT_ID_SSID);
        Hal_Mem_Free(ext->ssid);
        ext->ssid = NULL;
        lv_obj_set_style_local_text_color(lv_obj_get_child(ext->ok_btn, NULL),
                                          LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
    } else if(0 < len) {
        if(NULL == ext->ssid) {
            ext->ssid = text;
            lv_obj_add_style(ext->ssid_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_BLACK);
            lv_label_set_text(ext->ssid_label, text);
            HAL_WLAN_SECURITY_T security
                = lv_watch_get_free_num(lv_obj_get_parent(ext->security_txt_label));
            if(wlan_check_pwd_len(security, ext->pwd)) {
                lv_obj_set_style_local_text_color(lv_obj_get_child(ext->ok_btn, NULL),
                                                  LV_LABEL_PART_MAIN, LV_STATE_DEFAULT,
                                                  LV_COLOR_WHITE);
            }
        } else if(0 != strcmp(ext->ssid, text)) {
            Hal_Mem_Free(ext->ssid);
            ext->ssid = text;
            lv_label_set_text(ext->ssid_label, text);
        }
    }
}

static void wlan_add_nw_ssid_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_add_nw_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_ADD_NW);
    if(NULL == ext) return;

    keypad_para_t param;
    param.text = ext->ssid;
    param.password_mode = false;
    param.max_length = HAL_WLAN_MAX_SSID_LEN;
    param.min_length = 1;
    param.func = wlan_add_nw_get_ssid;
    keypad_create_btn_action(&param);
}

static void wlan_add_nw_get_pwd(char * text)
{
    wlan_add_nw_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_ADD_NW);
    if(NULL == ext) return;

    lv_obj_t * btn = lv_obj_get_parent(ext->security_txt_label);
    HAL_WLAN_SECURITY_T security = lv_watch_get_free_num(btn);
    wlan_get_pwd_handle(text, ext->ssid, security, &ext->pwd,
                        ext->pwd_label, ext->ok_btn);
}

static void wlan_add_nw_pwd_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_add_nw_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_ADD_NW);
    if(NULL == ext) return;

    lv_obj_t * security_btn = lv_obj_get_parent(ext->security_txt_label);
    HAL_WLAN_SECURITY_T security = lv_watch_get_free_num(security_btn);

    keypad_para_t param;
    param.text = ext->pwd;
    param.password_mode = true;
    param.max_length = HAL_WLAN_MAX_PWD_LEN;
    param.min_length = hal_wlan_get_min_pwd_len(security);
    param.func = wlan_add_nw_get_pwd;
    keypad_create_btn_action(&param);
}

static void wlan_add_nw_security_opt_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_add_nw_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_ADD_NW);
    if(NULL == ext) return;

    lv_obj_t * par = lv_obj_get_parent(btn);
    lv_obj_t * security_btn = lv_obj_get_parent(ext->security_txt_label);
    uint8_t cur_security = lv_watch_get_free_num(security_btn);
    uint8_t sel_security = lv_watch_get_free_num(btn);
    printf("%s: security, old %d, new %d\n", __FUNCTION__, cur_security, sel_security);
    if(cur_security != sel_security) {
        lv_watch_set_free_num(security_btn, sel_security);
        if(HAL_WLAN_SECURITY_OPEN == sel_security) {
            lv_label_set_text_id(ext->security_txt_label, WATCH_TEXT_ID_SECURITY_NONE);

            if(ext->pwd_label) {
                lv_obj_del(lv_obj_get_parent(ext->pwd_label));
                ext->pwd_label = NULL;
                if(ext->pwd) {
                    Hal_Mem_Free(ext->pwd);
                    ext->pwd = NULL;
                }
            }
        } else {
            char security_txt[20] = {};
            wlan_get_security_txt(sel_security, 20, security_txt);
            lv_label_set_text(ext->security_txt_label, security_txt);

            if(NULL == ext->pwd_label) {
                lv_obj_t * cont = lv_obj_get_parent(ext->ok_btn);
                lv_obj_t * ssid_btn = lv_obj_get_parent(ext->ssid_label);
                lv_obj_t * pwd_btn = lv_btn_create(cont, NULL);
                lv_obj_set_size(pwd_btn, lv_obj_get_width(ssid_btn),
                                lv_obj_get_height(ssid_btn));
                wlan_btn_set_input_style(pwd_btn);
                lv_obj_set_event_cb(pwd_btn, wlan_add_nw_pwd_btn_event_cb);
                lv_obj_align(pwd_btn, cont, LV_ALIGN_IN_TOP_MID, 0,
                             lv_obj_get_y(security_btn) + lv_obj_get_height(security_btn) +
                             lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN));
                lv_watch_obj_add_element(pwd_btn);

                ext->pwd_label = lv_label_create(pwd_btn, NULL);
                lv_obj_add_style(ext->pwd_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_GRAY);
                lv_label_set_long_mode(ext->pwd_label, LV_LABEL_LONG_SROLL_CIRC);
                lv_obj_set_width(ext->pwd_label, lv_obj_get_width(pwd_btn) - 10);
                lv_label_set_text_id(ext->pwd_label, WATCH_TEXT_ID_PASSWORD);
                lv_obj_align(ext->pwd_label, pwd_btn, LV_ALIGN_CENTER, 0, 0);
            }
        }

        if(ext->ssid) {
            if(wlan_check_pwd_len(sel_security, ext->pwd)) {
                lv_obj_set_style_local_text_color(lv_obj_get_child(ext->ok_btn, NULL),
                                                  LV_LABEL_PART_MAIN, LV_STATE_DEFAULT,
                                                  LV_COLOR_WHITE);
            } else {
                lv_obj_set_style_local_text_color(lv_obj_get_child(ext->ok_btn, NULL),
                                                  LV_LABEL_PART_MAIN, LV_STATE_DEFAULT,
                                                  LV_COLOR_GRAY);
            }
        }
    }

    lv_obj_del(lv_obj_get_parent(par));
}

static void wlan_add_nw_security_bg_btn_event_cb(lv_obj_t * cont, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    lv_obj_del(cont);
}

static void wlan_add_nw_show_security_option(lv_obj_t * par, HAL_WLAN_SECURITY_T index,
                                             lv_coord_t max_txt_width)
{
    if(HAL_WLAN_SECURITY_MAX <= index) {
        printf("%s: wrong index %d\n", __FUNCTION__, index);
        return;
    }

    printf("%s: index %d\n", __FUNCTION__, index);

    wlan_add_nw_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_ADD_NW);
    if(NULL == ext) return;

    lv_obj_t * bg_cont = lv_btn_create(par, NULL);
    lv_obj_set_style_local_bg_color(bg_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
    lv_obj_set_style_local_bg_opa(bg_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_30);
    lv_obj_set_style_local_radius(bg_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
    lv_cont_set_layout(bg_cont, LV_LAYOUT_OFF);
    lv_obj_set_size(bg_cont, lv_obj_get_width(par), lv_obj_get_height(par));
    lv_obj_set_event_cb(bg_cont, wlan_add_nw_security_bg_btn_event_cb);
    lv_obj_align(bg_cont, par, LV_ALIGN_CENTER, 0, 0);

    lv_obj_t * cont = lv_cont_create(bg_cont, NULL);
    lv_obj_add_style(cont, LV_CONT_PART_MAIN, &lv_style_pretty);
    lv_obj_set_style_local_bg_color(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
    lv_obj_set_style_local_bg_grad_color(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
    lv_obj_set_style_local_radius(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10);
    lv_obj_set_style_local_pad_top(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
    lv_obj_set_style_local_pad_bottom(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
    lv_obj_set_style_local_pad_left(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
    lv_obj_set_style_local_pad_right(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
    lv_obj_set_style_local_pad_inner(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
    lv_cont_set_fit2(cont, LV_FIT_NONE, LV_FIT_TIGHT);
    lv_obj_set_width(cont, max_txt_width + 8);
    lv_cont_set_layout(cont, LV_LAYOUT_COLUMN_MID);

    lv_coord_t font_h = lv_font_get_line_height(WLAN_DEF_FONT);
    for(uint8_t i = HAL_WLAN_SECURITY_OPEN;i < HAL_WLAN_SECURITY_MAX;i++) {
        lv_obj_t * btn = lv_btn_create(cont, NULL);
        lv_obj_clean_style_list(btn, LV_BTN_PART_MAIN);
        lv_obj_add_style(btn, LV_BTN_PART_MAIN, &lv_style_transp_tight);
        if(i == index) {
            lv_obj_set_style_local_bg_color(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_TEAL);
            lv_obj_set_style_local_bg_opa(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
            lv_obj_set_style_local_radius(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 4);
        }
        lv_obj_set_size(btn, lv_obj_get_width(cont), font_h + 2);
        lv_watch_set_free_num(btn, i);
        lv_obj_set_event_cb(btn, wlan_add_nw_security_opt_btn_event_cb);

        lv_obj_t * label = lv_label_create(btn, NULL);
        lv_obj_add_style(label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_BLACK);
        lv_obj_set_width(label, max_txt_width);
        char security_txt[20] = {};
        wlan_get_security_txt(i, 20, security_txt);
        lv_label_set_text(label, security_txt);
        lv_obj_align(label, btn, LV_ALIGN_CENTER, 0, 0);
    }

    if(LV_BIDI_DIR_RTL == lv_obj_get_base_dir(cont)) {
        lv_obj_align(cont, bg_cont, LV_ALIGN_IN_LEFT_MID, 10, 0);
    } else {
        lv_obj_align(cont, bg_cont, LV_ALIGN_IN_RIGHT_MID, -10, 0);
    }
}

static void wlan_add_nw_prepare_destroy(lv_obj_t * activity_obj)
{
    printf("%s\n", __FUNCTION__);

    lv_watch_png_cache_all_free();

    wlan_add_nw_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_ADD_NW);
    if(NULL == ext) {
        printf("%s: error, ui lost!\n", __FUNCTION__);
        return;
    }

    if(ext->ssid) {
        Hal_Mem_Free(ext->ssid);
    }
    if(ext->pwd) {
        Hal_Mem_Free(ext->pwd);
    }
}

static void wlan_add_nw_security_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    lv_obj_t * arrow_label = lv_obj_get_child(btn, NULL);
    wlan_add_nw_show_security_option(lv_obj_get_parent(btn),
                                     lv_watch_get_free_num(btn),
                                     lv_obj_get_width(btn) - 10 - lv_obj_get_width(arrow_label));
}

static void wlan_add_nw_cancel_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_del_ui(ACT_ID_WLAN_ADD_NW);
}

static void wlan_add_nw_create(void)
{
    lv_watch_activity_ext_t activity_ext;
    memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
    activity_ext.actId = ACT_ID_WLAN_ADD_NW;
    activity_ext.create = NULL;
    activity_ext.prepare_destory = wlan_add_nw_prepare_destroy;
    lv_obj_t * activity_obj = lv_watch_creat_activity_obj(&activity_ext);
    LV_ASSERT_MEM(activity_obj);

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    wlan_add_nw_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(wlan_add_nw_ext_t));
    LV_ASSERT_MEM(ext);

    ext->ssid = NULL;
    ext->pwd = NULL;
    ext->pwd_label = NULL;

    lv_obj_t * cont = wlan_add_bg(obj);

    lv_obj_t * title_cont = wlan_add_title(cont, WATCH_TEXT_ID_ADD_NW);

    lv_coord_t obj_w = lv_obj_get_width_fit(cont);
    lv_bidi_dir_t dir = lv_obj_get_base_dir(cont);

    lv_obj_t * ssid_btn = lv_btn_create(cont, NULL);
    wlan_btn_set_input_style(ssid_btn);
    lv_btn_set_fit2(ssid_btn, LV_FIT_NONE, LV_FIT_TIGHT);
    lv_obj_set_width(ssid_btn, obj_w);
    lv_obj_set_event_cb(ssid_btn, wlan_add_nw_ssid_btn_event_cb);
    lv_watch_obj_add_element(ssid_btn);

    ext->ssid_label = lv_label_create(ssid_btn, NULL);
    lv_obj_add_style(ext->ssid_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_GRAY);
    lv_label_set_long_mode(ext->ssid_label, LV_LABEL_LONG_SROLL_CIRC);
    lv_obj_set_width(ext->ssid_label, lv_obj_get_width_fit(ssid_btn));
    lv_label_set_text_id(ext->ssid_label, WATCH_TEXT_ID_SSID);

    lv_obj_t * security_label = lv_label_create(cont, NULL);
    lv_obj_add_style(security_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    lv_label_set_long_mode(security_label, LV_LABEL_LONG_SROLL_CIRC);
    lv_obj_set_width(security_label, obj_w);
    lv_label_set_text_id(security_label, WATCH_TEXT_ID_SECURITY);

    lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(cont, LV_CONT_PART_MAIN);
    lv_coord_t pad_inner = (lv_obj_get_height_fit(cont) - lv_obj_get_height(title_cont) -
                            4 * lv_obj_get_height(ssid_btn) - lv_obj_get_height(security_label)) / 5;
    lv_obj_set_style_local_pad_inner(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, pad_inner);

    lv_obj_align(ssid_btn, title_cont, LV_ALIGN_OUT_BOTTOM_MID, 0, pad_inner);
    lv_obj_align(security_label, ssid_btn, LV_ALIGN_OUT_BOTTOM_MID, 0, pad_inner);

    lv_obj_t * security_btn = lv_btn_create(cont, NULL);
    lv_obj_clean_style_list(security_btn, LV_BTN_PART_MAIN);
    lv_obj_add_style(security_btn, LV_BTN_PART_MAIN, &lv_style_pretty);
    lv_obj_set_style_local_bg_color(security_btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
                                    LV_COLOR_WHITE);
    lv_obj_set_style_local_bg_grad_color(security_btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
                                         LV_COLOR_WHITE);
    lv_obj_set_style_local_bg_opa(security_btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
    lv_obj_set_style_local_pad_left(security_btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 5);
    lv_obj_set_style_local_pad_right(security_btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 5);
    lv_obj_set_style_local_pad_inner(security_btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 2);
    lv_btn_set_layout(security_btn, LV_LAYOUT_ROW_MID);
    lv_btn_set_fit2(security_btn, LV_FIT_TIGHT, LV_FIT_NONE);
    lv_obj_set_height(security_btn, lv_obj_get_height(ssid_btn));
    lv_watch_set_free_num(security_btn, HAL_WLAN_SECURITY_OPEN);
    lv_obj_set_event_cb(security_btn, wlan_add_nw_security_btn_event_cb);
    lv_watch_obj_add_element(security_btn);

    lv_coord_t max_txt_w = 0;
    lv_coord_t letter_space
        = lv_obj_get_style_text_letter_space(security_label, LV_LABEL_PART_MAIN);
    for(uint8_t i = HAL_WLAN_SECURITY_OPEN;i < HAL_WLAN_SECURITY_MAX;i++) {
        char security_txt[20] = {};
        wlan_get_security_txt(i, 20, security_txt);
        lv_coord_t txt_w
            = _lv_txt_get_width(security_txt, strlen(security_txt),
                                WLAN_DEF_FONT, letter_space, LV_TXT_FLAG_NONE);
        if(max_txt_w < txt_w) {
            max_txt_w = txt_w;
        }
    }
    ext->security_txt_label = lv_label_create(security_btn, NULL);
    lv_obj_add_style(ext->security_txt_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_BLACK);
    lv_label_set_long_mode(ext->security_txt_label, LV_LABEL_LONG_SROLL_CIRC);
    lv_obj_set_width(ext->security_txt_label, max_txt_w);
    lv_label_set_text_id(ext->security_txt_label, WATCH_TEXT_ID_SECURITY_NONE);

    lv_obj_t * arrow_label = lv_label_create(security_btn, NULL);
    lv_obj_add_style(arrow_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_BLACK);
    lv_label_set_text(arrow_label, LV_SYMBOL_DOWN);

    if(LV_BIDI_DIR_RTL == dir) {
        lv_obj_align(security_btn, security_label, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, pad_inner);
    } else {
        lv_obj_align(security_btn, security_label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, pad_inner);
    }

    ext->ok_btn = lv_btn_create(cont, NULL);
    lv_obj_set_size(ext->ok_btn, lv_obj_get_width(cont) * 3 / 7, lv_obj_get_height(ssid_btn));
    wlan_btn_set_normal_style(ext->ok_btn);
    lv_obj_set_event_cb(ext->ok_btn, wlan_add_nw_ok_btn_event_cb);
    lv_watch_obj_add_element(ext->ok_btn);

    lv_obj_t * ok_label = lv_label_create(ext->ok_btn, NULL);
    lv_obj_add_style(ok_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    lv_obj_set_style_local_text_color(ok_label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
    lv_label_set_text_id(ok_label, WATCH_TEXT_ID_OK);
    lv_obj_align(ok_label, ext->ok_btn, LV_ALIGN_CENTER, 0, 0);

    ext->cancel_btn = lv_btn_create(cont, ext->ok_btn);
    wlan_btn_set_normal_style(ext->cancel_btn);
    lv_obj_set_event_cb(ext->cancel_btn, wlan_add_nw_cancel_btn_event_cb);
    lv_watch_obj_add_element(ext->cancel_btn);

    lv_obj_t * cancel_label = lv_label_create(ext->cancel_btn, NULL);
    lv_obj_add_style(cancel_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    lv_label_set_text_id(cancel_label, WATCH_TEXT_ID_CANCEL);
    lv_obj_align(cancel_label, ext->cancel_btn, LV_ALIGN_CENTER, 0, 0);

    if(LV_BIDI_DIR_RTL == dir) {
        lv_obj_align(ext->cancel_btn, cont, LV_ALIGN_IN_BOTTOM_RIGHT, -10, -pad_bottom);
        lv_obj_align(ext->ok_btn, cont, LV_ALIGN_IN_BOTTOM_LEFT, 10, -pad_bottom);
    } else {
        lv_obj_align(ext->ok_btn, cont, LV_ALIGN_IN_BOTTOM_RIGHT, -10, -pad_bottom);
        lv_obj_align(ext->cancel_btn, cont, LV_ALIGN_IN_BOTTOM_LEFT, 10, -pad_bottom);
    }
}

static void wlan_option_add_nw_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_add_nw_create();
}
#endif

static void wlan_option_saved_nw_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_saved_nw_create();
}

static void wlan_option_sel_nw_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    lv_obj_t * sw = lv_obj_get_child(btn, NULL);
    hal_wlan_info_t * wlan_info = hal_wlan_get_info();
    bool is_auto;
    if(wlan_info->is_auto_sel_nw) {
        lv_switch_off(sw, false);
        is_auto = false;
    } else {
        lv_switch_on(sw, false);
        is_auto = true;
    }
    hal_wlan_ui_set_auto_sel_nw(is_auto);
}

static void wlan_option_prepare_destroy(lv_obj_t * activity_obj)
{
    printf("%s\n", __FUNCTION__);
}

static void wlan_set_sw_style(lv_obj_t * sw)
{
    lv_obj_set_style_local_bg_color(sw, LV_SWITCH_PART_BG, LV_STATE_DEFAULT, LV_COLOR_GRAY);
    lv_obj_set_style_local_border_width(sw, LV_SWITCH_PART_BG, LV_STATE_DEFAULT, 0);
    lv_obj_set_style_local_bg_color(sw, LV_SWITCH_PART_INDIC, LV_STATE_DEFAULT,
                                    LV_COLOR_MAKE(0x0B,0x85,0xFF));
}

static void wlan_option_add_btn(lv_obj_t * list, lv_obj_t * saved_ap_btn)
{
    if(NULL == list) {
        printf("%s: warning, list is NULL\n", __FUNCTION__);
        return;
    }

    if(NULL == saved_ap_btn) {
        printf("%s: warning, saved_ap_btn is NULL\n", __FUNCTION__);
        return;
    }

    hal_wlan_info_t * wlan_info = hal_wlan_get_info();
    if((NULL == wlan_info)
       || (wlan_info
           && ((HAL_WLAN_STATE_INIT == wlan_info->state)
               || (HAL_WLAN_STATE_DEINIT == wlan_info->state)))) {
        return;
    }

    lv_obj_t * saved_ap_label = lv_obj_get_child_back(saved_ap_btn, NULL);

#if USE_LV_WATCH_KEYPAD != 0
    lv_obj_t * add_nw_btn = lv_btn_create(list, saved_ap_btn);
    lv_obj_set_event_cb(add_nw_btn, wlan_option_add_nw_btn_event_cb);
    lv_watch_obj_add_element(add_nw_btn);

    lv_obj_t * add_nw_label = lv_label_create(add_nw_btn, saved_ap_label);
    lv_label_set_text_id(add_nw_label, WATCH_TEXT_ID_ADD_NW);
#endif

    lv_obj_t * sel_nw_btn = lv_btn_create(list, saved_ap_btn);
    lv_obj_set_event_cb(sel_nw_btn, wlan_option_sel_nw_btn_event_cb);
    lv_watch_obj_add_element(sel_nw_btn);

    lv_obj_t * sel_nw_label = lv_label_create(sel_nw_btn, saved_ap_label);
    lv_label_set_text_id(sel_nw_label, WATCH_TEXT_ID_AUTO_SEL_NW);

    lv_obj_t * sw = lv_switch_create(sel_nw_btn, NULL);
    wlan_set_sw_style(sw);
    lv_font_t * font = (lv_font_t *)lv_obj_get_style_text_font(sel_nw_label, LV_LABEL_PART_MAIN);
    lv_coord_t font_h = lv_font_get_line_height(font);
    lv_obj_set_size(sw, font_h * 7 / 6, font_h * 7 / 12);
    if(wlan_info->is_auto_sel_nw) {
        lv_switch_on(sw, false);
    }
    lv_obj_set_click(sw, false);

    lv_coord_t pad_inner = lv_obj_get_style_pad_inner(sel_nw_btn, LV_BTN_PART_MAIN);
    lv_obj_set_width(sel_nw_label,
                     lv_obj_get_width_fit(sel_nw_btn) - pad_inner - lv_obj_get_width(sw));
}

static void wlan_option_create(void)
{
    lv_watch_activity_ext_t activity_ext;
    memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
    activity_ext.actId = ACT_ID_WLAN_OPTION;
    activity_ext.create = NULL;
    activity_ext.prepare_destory = wlan_option_prepare_destroy;
    lv_obj_t * activity_obj = lv_watch_creat_activity_obj(&activity_ext);
    LV_ASSERT_MEM(activity_obj);

    wlan_ext_t * ext = wlan_get_ext(ACT_ID_WLAN);
    if(NULL == ext) return;

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);

    lv_obj_t * cont = wlan_add_bg(obj);

    lv_obj_t * title_cont = wlan_add_title(cont, WATCH_TEXT_ID_SETTINGS);

    lv_obj_t * list = lv_list_create(cont, NULL);
    wlan_list_set_common_param(list);
    lv_obj_set_size(list, lv_obj_get_width_fit(cont),
                    lv_obj_get_height(cont) - lv_obj_get_y(title_cont)
                    - lv_obj_get_height(title_cont) - 6);
    lv_obj_align(list, cont, LV_ALIGN_IN_BOTTOM_MID, 0, -2);

    lv_obj_t * saved_ap_btn = lv_btn_create(list, NULL);
    lv_obj_add_style(saved_ap_btn, LV_BTN_PART_MAIN, &ext->btn_style);
    lv_btn_set_fit2(saved_ap_btn, LV_FIT_NONE, LV_FIT_TIGHT);
    lv_obj_set_width(saved_ap_btn, lv_obj_get_width(list));
    lv_btn_set_layout(saved_ap_btn, LV_LAYOUT_ROW_MID);
    lv_obj_set_event_cb(saved_ap_btn, wlan_option_saved_nw_btn_event_cb);
    lv_page_glue_obj(saved_ap_btn, true);
    lv_watch_obj_add_element(saved_ap_btn);

    lv_obj_t * saved_ap_label = lv_label_create(saved_ap_btn, NULL);
    lv_obj_add_style(saved_ap_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    lv_label_set_long_mode(saved_ap_label, LV_LABEL_LONG_BREAK);
    lv_obj_set_width(saved_ap_label, lv_obj_get_width_fit(saved_ap_btn));
    lv_label_set_text_id(saved_ap_label, WATCH_TEXT_ID_SAVED_NW);

    wlan_option_add_btn(list, saved_ap_btn);
}

static lv_obj_t * wlan_dialog_get_ok_btn(lv_obj_t * content)
{
    lv_obj_t * cont = lv_obj_get_parent(content);
    return lv_obj_get_child_back(lv_obj_get_child_back(cont, content), NULL);
}

static void wlan_dialog_anim_end_cb(lv_anim_t * anim)
{
    lv_obj_t * cont = (lv_obj_t *)anim->var;

    lv_obj_t * bg = lv_obj_get_parent(cont);
    bool is_del_dialog_only = lv_watch_get_free_num(bg);
    if(is_del_dialog_only) {
        lv_obj_del(bg);
    } else {
        lv_watch_Activity_Id_t act_id = lv_watch_get_free_num(cont);
        wlan_del_ui(act_id);
    }
}

static void wlan_dialog_anim(lv_obj_t * obj, lv_coord_t start, lv_coord_t end)
{
    lv_anim_path_t path;
    lv_anim_path_init(&path);
    lv_anim_path_set_cb(&path, lv_anim_path_linear);
    lv_anim_t a = {};
    lv_anim_init(&a);
    lv_anim_set_var(&a, obj);
    lv_anim_set_values(&a, start, end);
    lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y);
    if(start < end) {
        lv_anim_set_ready_cb(&a, wlan_dialog_anim_end_cb);
    }
    lv_anim_set_time(&a, 100);
    lv_anim_set_path(&a, &path);
    lv_anim_start(&a);
}

static void wlan_dialog_bg_event_cb(lv_obj_t * cont, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    lv_obj_t * child = lv_obj_get_child(cont, NULL);
    if(lv_anim_get(child, NULL)) {
        printf("%s: anim\n", __FUNCTION__);
        return;
    }

    printf("%s:\n", __FUNCTION__);

    wlan_dialog_anim(child, lv_obj_get_y(child), lv_obj_get_height(cont));
}

static void wlan_dialog_ok_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    bool ret = true;

    WLAN_DIALOG_OK_BTN_EVENT_CB cb = (WLAN_DIALOG_OK_BTN_EVENT_CB)lv_watch_get_free_ptr(btn);
    if(cb) {
        ret = cb(btn);
    }
    printf("%s: ret %d\n", __FUNCTION__, ret);
    if(ret) {
        lv_obj_t * cont = lv_obj_get_parent(lv_obj_get_parent(btn));
        lv_anim_del(cont, NULL);
        lv_watch_set_free_num(lv_obj_get_parent(cont), false);
        wlan_dialog_anim(cont, lv_obj_get_y(cont), lv_obj_get_height(lv_obj_get_parent(cont)));
        lv_obj_set_click(btn, false);
        lv_obj_set_click(lv_obj_get_child_back(cont, btn), false);
    }
}

static void wlan_dialog_cancel_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    printf("%s\n", __FUNCTION__);

    lv_obj_t * cont = lv_obj_get_parent(lv_obj_get_parent(btn));
    lv_anim_del(cont, NULL);
    wlan_dialog_anim(cont, lv_obj_get_y(cont), lv_obj_get_height(lv_obj_get_parent(cont)));
    lv_obj_set_click(btn, false);
    lv_obj_set_click(lv_obj_get_child(cont, btn), false);
}

static lv_obj_t * wlan_dialog_create(lv_obj_t * obj, uint16_t act_id, bool is_del_dialog_only,
                                     WLAN_DIALOG_OK_BTN_EVENT_CB ok_cb)
{
    if(false == is_del_dialog_only) {
        lv_obj_t * img = lv_obj_get_parent(obj);
        lv_obj_set_style_local_image_opa(img, LV_IMG_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0);
        lv_obj_t * activity_obj = lv_obj_get_parent(img);
        lv_obj_set_style_local_bg_opa(activity_obj, LV_IMG_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0);
    }

    lv_coord_t w = lv_obj_get_width(obj);
    lv_coord_t h = lv_obj_get_height(obj);

    lv_obj_t * bg = lv_cont_create(obj, NULL);
    lv_obj_add_style(bg, LV_CONT_PART_MAIN, &lv_style_transp_tight);
    lv_cont_set_layout(bg, LV_LAYOUT_OFF);
    lv_obj_set_size(bg, w, h);
    lv_watch_set_free_num(bg, is_del_dialog_only); // delete act id if is_del_dialog_only is false
    lv_obj_set_event_cb(bg, wlan_dialog_bg_event_cb);
    lv_obj_align(bg, obj, LV_ALIGN_CENTER, 0, 0);

    lv_coord_t font_h = lv_font_get_line_height(WLAN_DEF_FONT);

    lv_obj_t * cont = lv_cont_create(bg, NULL);
    lv_obj_set_style_local_bg_opa(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
    lv_obj_set_style_local_bg_color(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT,
                                    LV_COLOR_MAKE(60, 60, 60));
    lv_coord_t radius = w / 10;
    lv_obj_set_style_local_radius(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, radius);
    lv_coord_t ver = font_h / 2;
    lv_obj_set_style_local_pad_top(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, ver);
    lv_obj_set_style_local_pad_bottom(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, ver + radius);
    lv_obj_set_style_local_pad_inner(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, font_h / 3);
    lv_cont_set_layout(cont, LV_LAYOUT_COLUMN_MID);
    lv_cont_set_fit2(cont, LV_FIT_NONE, LV_FIT_TIGHT);
    lv_obj_set_width(cont, w);
    lv_watch_set_free_num(cont, act_id);

    lv_obj_t * title_label = lv_label_create(cont, NULL);
    lv_obj_add_style(title_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    lv_label_set_align(title_label, LV_LABEL_ALIGN_CENTER);
    lv_label_set_long_mode(title_label, LV_LABEL_LONG_SROLL_CIRC);
    lv_obj_set_width(title_label, w - 20);

    lv_obj_t * content = lv_cont_create(cont, NULL);
    lv_obj_add_style(content, LV_CONT_PART_MAIN, &lv_style_transp_tight);
    lv_cont_set_layout(content, LV_LAYOUT_OFF);
    lv_cont_set_fit2(content, LV_FIT_NONE, LV_FIT_TIGHT);
    lv_obj_set_width(content, w);
    lv_obj_set_click(content, false);

    lv_obj_t * btn_cont = lv_cont_create(cont, content);

    lv_obj_t * ok_btn = lv_btn_create(btn_cont, NULL);
    wlan_btn_set_normal_style(ok_btn);
    lv_obj_set_size(ok_btn, w / 3, font_h * 3 / 2);
    lv_obj_set_event_cb(ok_btn, wlan_dialog_ok_btn_event_cb);
    lv_watch_set_free_ptr(ok_btn, ok_cb);

    lv_obj_t * ok_label = lv_label_create(ok_btn, NULL);
    lv_obj_set_style_local_text_font(ok_label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, WLAN_DEF_FONT);

    lv_obj_t * cancel_btn = lv_btn_create(btn_cont, ok_btn);
    lv_obj_set_event_cb(cancel_btn, wlan_dialog_cancel_btn_event_cb);

    lv_obj_t * cancel_label = lv_label_create(cancel_btn, ok_label);
    lv_obj_set_style_local_text_color(cancel_label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT,
                                      LV_COLOR_WHITE);
    lv_label_set_text_id(cancel_label, WATCH_TEXT_ID_CANCEL);
    lv_obj_align(cancel_label, cancel_btn, LV_ALIGN_CENTER, 0, 0);

    if(LV_BIDI_DIR_RTL == lv_obj_get_base_dir(cont)) {
        lv_obj_align(cancel_btn, btn_cont, LV_ALIGN_IN_TOP_RIGHT, -w / 9, 0);
        lv_obj_align(ok_btn, btn_cont, LV_ALIGN_IN_TOP_LEFT, w / 9, 0);
    } else {
        lv_obj_align(ok_btn, btn_cont, LV_ALIGN_IN_TOP_RIGHT, -w / 9, 0);
        lv_obj_align(cancel_btn, btn_cont, LV_ALIGN_IN_TOP_LEFT, w / 9, 0);
    }

    return content;
}

static void wlan_dialog_anim_start(lv_obj_t * cont)
{
    lv_obj_t * bg = lv_obj_get_parent(cont);
    lv_coord_t cont_h = lv_obj_get_height(cont);
    lv_coord_t h = lv_obj_get_height(bg);
    wlan_dialog_anim(cont, h, h - cont_h + lv_obj_get_style_radius(cont, LV_CONT_PART_MAIN));
}

static bool wlan_saved_ap_del_nw_ok_btn_event_cb(lv_obj_t * btn)
{
    wlan_saved_ap_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_SAVED_AP);
    if(NULL == ext) {
        printf("%s: warning, not find wlan saved ap\n", __FUNCTION__);
        return true;
    }

    printf("%s: sec %d, ssid %s\n", __FUNCTION__, ext->ap.security, ext->ap.ssid);

    hal_wlan_ui_del_saved_nw(ext->ap.ssid, ext->ap.security);

    return true;
}

static void wlan_saved_ap_del_nw_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_WLAN_SAVED_AP);
    if(NULL == activity_obj) {
        printf("%s: warning, activity_obj is NULL\n", __FUNCTION__);
        return;
    }

    lv_obj_t * obj = NULL;
    lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &obj);
    if(NULL == obj) {
        printf("%s: warning, obj is NULL\n", __FUNCTION__);
        return;
    }

    lv_obj_t * content = wlan_dialog_create(obj, ACT_ID_WLAN_SAVED_AP, true,
                                            wlan_saved_ap_del_nw_ok_btn_event_cb);

    lv_obj_t * cont = lv_obj_get_parent(content);

    lv_obj_t * title_label = lv_obj_get_child_back(cont, NULL);
    lv_label_set_text_id(title_label, WATCH_TEXT_ID_DEL_NW);

    lv_obj_t * ok_btn = wlan_dialog_get_ok_btn(content);
    wlan_btn_set_normal_style(ok_btn);
    lv_obj_set_style_local_bg_color(ok_btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
                                    LV_COLOR_MAKE(17, 155, 238));

    lv_obj_t * ok_label = lv_obj_get_child(ok_btn, NULL);
    lv_obj_set_style_local_text_color(ok_label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
    lv_label_set_text_id(ok_label, WATCH_TEXT_ID_OK);
    lv_obj_align(ok_label, ok_btn, LV_ALIGN_CENTER, 0, 0);

    lv_obj_del(content);

    wlan_dialog_anim_start(cont);
}

static void wlan_saved_ap_conn_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_saved_ap_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_SAVED_AP);
    if(NULL == ext) {
        printf("%s: warning, ext is NULL\n", __FUNCTION__);
        return;
    }

    printf("%s:ssid %s\n", __FUNCTION__, ext->ap.ssid);

    hal_wlan_ui_open_ap(ext->ap.ssid, ext->ap.security, NULL);

    wlan_del_ui(ACT_ID_WLAN_SAVED_AP);
}

#if USE_LV_WATCH_KEYPAD != 0
static void wlan_saved_ap_get_new_pwd(char * pwd)
{
    if(NULL == pwd) {
        printf("%s: warning, pwd is NULL\n", __FUNCTION__);
        return;
    }

    wlan_saved_ap_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_SAVED_AP);
    if(NULL == ext) {
        printf("%s: warning, ext is NULL\n", __FUNCTION__);
        Hal_Mem_Free(pwd);
        return;
    }

    printf("%s: pwd chg, ssid %s, security %d, pwd %s\n",
           __FUNCTION__, ext->ap.ssid, ext->ap.security, pwd);

    if(!wlan_check_pwd_len(ext->ap.security, pwd)) {
        printf("%s: warning, invalid pwd\n", __FUNCTION__);
        Hal_Mem_Free(pwd);
        return;
    }

    hal_wlan_ui_open_ap(ext->ap.ssid, ext->ap.security, pwd);

    Hal_Mem_Free(pwd);

    wlan_del_ui(ACT_ID_WLAN_SAVED_AP);
}

static void wlan_saved_ap_mod_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_saved_ap_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_SAVED_AP);
    if(NULL == ext) {
        printf("%s: warning, ext is NULL\n", __FUNCTION__);
        return;
    }

    printf("%s:ssid %s\n", __FUNCTION__, ext->ap.ssid);

    keypad_para_t param;
    param.text = NULL;
    param.password_mode = true;
    param.max_length = HAL_WLAN_MAX_PWD_LEN;
    param.min_length = hal_wlan_get_min_pwd_len(ext->ap.security);
    param.func = wlan_saved_ap_get_new_pwd;
    keypad_create_btn_action(&param);
}
#endif

static void wlan_saved_ap_create(hal_wlan_ap_t * ap, WLAN_BTN_TYPE_T type)
{
    if(NULL == ap) {
        printf("%s: error, ap info lost!\n", __FUNCTION__);
        return;
    }

    lv_watch_activity_ext_t activity_ext;
    memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
    activity_ext.actId = ACT_ID_WLAN_SAVED_AP;
    activity_ext.create = NULL;
    activity_ext.prepare_destory = NULL;
    lv_obj_t * activity_obj = lv_watch_creat_activity_obj(&activity_ext);
    LV_ASSERT_MEM(activity_obj);

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    wlan_saved_ap_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(wlan_saved_ap_ext_t));
    LV_ASSERT_MEM(ext);

    Hal_Mem_Copy(&ext->ap, ap, sizeof(hal_wlan_ap_t));
    printf("%s: ap %s, sec %d\n", __FUNCTION__, ap->ssid, ap->security);

    lv_obj_t * cont = wlan_add_bg(obj);

    lv_coord_t pad_top = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN);
    lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(cont, LV_CONT_PART_MAIN);

    lv_obj_t * title_label = lv_label_create(cont, NULL);
    lv_obj_add_style(title_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    lv_label_set_align(title_label, LV_LABEL_ALIGN_CENTER);
    lv_label_set_long_mode(title_label, LV_LABEL_LONG_SROLL_CIRC);
    lv_obj_set_width(title_label, lv_obj_get_width_fit(cont) - 20);
    lv_label_set_text(title_label, ap->ssid);
    lv_obj_align(title_label, cont, LV_ALIGN_IN_TOP_MID, 0, pad_top);

    lv_obj_t * list = lv_list_create(cont, NULL);
    wlan_list_set_common_param(list);
    lv_obj_set_size(list, lv_obj_get_width_fit(cont),
                    lv_obj_get_height(cont) - lv_obj_get_y(title_label)-
                    lv_obj_get_height(title_label) - 2 - pad_bottom);
    lv_obj_align(list, cont, LV_ALIGN_IN_BOTTOM_MID, 0, -pad_bottom);

    lv_obj_t * detail_cont = wlan_add_ap_info(list, ap);

    if((WLAN_BTN_TYPE_ACT == type) || (WLAN_BTN_TYPE_NO_INTERNET == type)) {
        lv_obj_t * ip_label = lv_label_create(detail_cont, lv_obj_get_child(detail_cont, NULL));
        lv_label_set_text_id(ip_label, WATCH_TEXT_ID_IP_ADDRESS);
        hal_wlan_info_t * wlan_info = hal_wlan_get_info();
        lv_label_ins_text(ip_label, LV_LABEL_POS_LAST, wlan_info->ip);
    }

    lv_coord_t font_h = lv_font_get_line_height(WLAN_DEF_FONT);

    if((WLAN_BTN_TYPE_ACT != type) && (WLAN_BTN_TYPE_NO_INTERNET != type)) {
        lv_obj_t * conn_btn = lv_btn_create(list, NULL);
        wlan_btn_set_normal_style(conn_btn);
        lv_page_glue_obj(conn_btn, true);
        lv_obj_set_size(conn_btn, lv_obj_get_width_fit(cont), font_h + 10);
        lv_obj_set_event_cb(conn_btn, wlan_saved_ap_conn_btn_event_cb);
        lv_watch_obj_add_element(conn_btn);

        lv_obj_t * conn_label = lv_label_create(conn_btn, NULL);
        lv_obj_add_style(conn_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
        lv_label_set_text_id(conn_label, WATCH_TEXT_ID_CONNECT);
        lv_obj_align(conn_label, conn_btn, LV_ALIGN_CENTER, 0, 0);
    }

    if((HAL_WLAN_SECURITY_OPEN != ext->ap.security)
       && (WLAN_BTN_TYPE_ACT != type)
       && (WLAN_BTN_TYPE_NO_INTERNET != type)) {
#if USE_LV_WATCH_KEYPAD != 0
        lv_obj_t * mod_btn = lv_btn_create(list, NULL);
        wlan_btn_set_normal_style(mod_btn);
        lv_page_glue_obj(mod_btn, true);
        lv_obj_set_size(mod_btn, lv_obj_get_width_fit(cont), font_h + 10);
        lv_obj_set_event_cb(mod_btn, wlan_saved_ap_mod_btn_event_cb);
        lv_watch_obj_add_element(mod_btn);

        lv_obj_t * mod_label = lv_label_create(mod_btn, NULL);
        lv_obj_add_style(mod_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
        lv_label_set_text_id(mod_label, WATCH_TEXT_ID_MOD_PWD);
        lv_obj_align(mod_label, mod_btn, LV_ALIGN_CENTER, 0, 0);
#endif
    }

    lv_obj_t * del_nw_btn = lv_btn_create(list, NULL);
    wlan_btn_set_normal_style(del_nw_btn);
    lv_page_glue_obj(del_nw_btn, true);
    lv_obj_set_size(del_nw_btn, lv_obj_get_width_fit(list), font_h + 10);
    lv_obj_set_event_cb(del_nw_btn, wlan_saved_ap_del_nw_btn_event_cb);
    lv_watch_obj_add_element(del_nw_btn);

    lv_obj_t * del_nw_label = lv_label_create(del_nw_btn, NULL);
    lv_obj_add_style(del_nw_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
    lv_obj_set_style_local_text_color(del_nw_label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT,
                                      LV_COLOR_MAKE(255, 80, 80));
    lv_label_set_text_id(del_nw_label, WATCH_TEXT_ID_DEL_NW);
    lv_obj_align(del_nw_label, del_nw_btn, LV_ALIGN_CENTER, 0, 0);
}

static void wlan_option_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_option_create();
}

static void wlan_saved_ap_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    WLAN_BTN_TYPE_T type = lv_watch_get_free_num(btn);
    hal_wlan_ap_t * ap = lv_watch_get_free_ptr(lv_obj_get_child_back(btn, NULL));
    printf("%s: ssid %s, security %d\n", __FUNCTION__, ap->ssid, ap->security);
    wlan_saved_ap_create(ap, type);
}

static void wlan_non_saved_ap_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    hal_wlan_ap_t * ap = lv_watch_get_free_ptr(lv_obj_get_child_back(btn, NULL));
    wlan_login_create(ap);
}

static void wlan_refresh_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_ext_t * ext = wlan_get_ext(ACT_ID_WLAN);
    if(!ext) {
        printf("%s: warning, ext is NULL\n", __FUNCTION__);
        return;
    }
    WLAN_BTN_TYPE_T type = (WLAN_BTN_TYPE_T)lv_watch_get_free_num(btn);
    if(WLAN_BTN_TYPE_REFRESHING == type) {
        return;
    }
    if(hal_wlan_ui_scan_ap()) {
        lv_watch_set_free_num(btn, WLAN_BTN_TYPE_REFRESHING);
        wlan_play_refreshing_anim(ext->refresh_img);
    }
}

static lv_obj_t * wlan_add_btn(wlan_ext_t * ext, lv_obj_t * cur_btn, WLAN_BTN_TYPE_T type,
                               hal_wlan_ap_t * ap)
{
    bool is_in_anim = false;
    lv_obj_t * btn;
    lv_coord_t font_h = lv_font_get_line_height(WLAN_DEF_FONT);
    lv_coord_t btn_w = lv_obj_get_width_fit(ext->list);
    if(cur_btn) {
        if((WLAN_BTN_TYPE_OPENING == lv_watch_get_free_num(cur_btn))
           || (WLAN_BTN_TYPE_GETTING_IP == lv_watch_get_free_num(cur_btn))
           || (WLAN_BTN_TYPE_REFRESHING == lv_watch_get_free_num(cur_btn))) {
            is_in_anim = true;
        }
        btn = cur_btn;
    } else {
        btn = lv_btn_create(ext->list, NULL);
        lv_obj_add_style(btn, LV_BTN_PART_MAIN, &ext->btn_style);
        if((WLAN_BTN_TYPE_REFRESH == type) || (WLAN_BTN_TYPE_REFRESHING == type)) {
            lv_obj_set_style_local_bg_opa(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_30);
            lv_obj_set_style_local_bg_color(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
            lv_obj_set_style_local_radius(btn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 5);
        }
        lv_btn_set_fit2(btn, LV_FIT_NONE, LV_FIT_TIGHT);
        lv_obj_set_width(btn, btn_w);
        lv_btn_set_layout(btn, LV_LAYOUT_ROW_MID);
        lv_page_glue_obj(btn, true);
        lv_watch_obj_add_element(btn);
    }
    lv_watch_set_free_num(btn, type);
    if((WLAN_BTN_TYPE_ACT == type) || (WLAN_BTN_TYPE_NO_INTERNET == type)) {
        lv_obj_set_event_cb(btn, wlan_saved_ap_btn_event_cb);
    } else if((WLAN_BTN_TYPE_OPENING == type)
              || (WLAN_BTN_TYPE_REFRESHING == type)
              || (WLAN_BTN_TYPE_GETTING_IP == type)) {
        lv_obj_set_event_cb(btn, NULL);
    } else if(WLAN_BTN_TYPE_REFRESH == type) {
        lv_obj_set_event_cb(btn, wlan_refresh_btn_event_cb);
    } else if((WLAN_BTN_TYPE_OPEN_FAIL == type)
              || (WLAN_BTN_TYPE_SAVED == type)
              || (WLAN_BTN_TYPE_PASSWORD_ERROR == type)) {
        lv_obj_set_event_cb(btn, wlan_saved_ap_btn_event_cb);
    } else if(WLAN_BTN_TYPE_SCAN_LIST == type) {
        lv_obj_set_event_cb(btn, wlan_non_saved_ap_btn_event_cb);
    }

    lv_coord_t pad_top = lv_obj_get_style_pad_top(btn, LV_BTN_PART_MAIN);
    lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(btn, LV_BTN_PART_MAIN);
    lv_coord_t pad_inner = lv_obj_get_style_pad_inner(btn, LV_BTN_PART_MAIN);

    bool is_multi_label = false;
    if((WLAN_BTN_TYPE_ACT == type)
       || (WLAN_BTN_TYPE_NO_INTERNET == type)
       || (WLAN_BTN_TYPE_OPENING == type)
       || (WLAN_BTN_TYPE_GETTING_IP == type)
       || (WLAN_BTN_TYPE_SAVED == type)
       || (WLAN_BTN_TYPE_OPEN_FAIL == type)
       || (WLAN_BTN_TYPE_PASSWORD_ERROR == type)) {
        is_multi_label = true;
    }

    lv_obj_t * label1;
    lv_obj_t * label_cont = NULL;
    if(cur_btn) {
        if(is_multi_label) {
            label_cont = lv_obj_get_child_back(btn, NULL);
            label1 = lv_obj_get_child_back(label_cont, NULL);
        } else {
            label1 = lv_obj_get_child_back(btn, NULL);
        }
        if((WLAN_BTN_TYPE_REFRESH != type) && (WLAN_BTN_TYPE_REFRESHING != type)) {
            lv_label_set_text(label1, ap->ssid);
        }
    } else {
        if(is_multi_label) {
            label_cont = lv_cont_create(btn, NULL);
            lv_obj_add_style(label_cont, LV_CONT_PART_MAIN, &lv_style_transp_tight);
            lv_obj_set_click(label_cont, false);
            lv_cont_set_fit(label_cont, LV_FIT_TIGHT);
            lv_cont_set_layout(label_cont, LV_LAYOUT_COLUMN_MID);

            label1 = lv_label_create(label_cont, NULL);
        } else {
            label1 = lv_label_create(btn, NULL);
        }
        lv_obj_add_style(label1, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
        lv_label_set_long_mode(label1, LV_LABEL_LONG_SROLL_CIRC);
        if((WLAN_BTN_TYPE_REFRESH == type) || (WLAN_BTN_TYPE_REFRESHING == type)) {
            lv_label_set_text_id(label1, WATCH_TEXT_ID_REFRESH_NETWORK);
        } else {
            lv_label_set_text(label1, ap->ssid);
        }
    }
    lv_obj_t * first_child = lv_obj_get_child_back(btn, NULL);
    hal_wlan_ap_t * cur_ap = lv_watch_get_free_ptr(first_child);
    if(ap) {
        /* printf("%s: type %d, ssid %s, anim %d, cur_btn %p, btn %p\n", */
        /*        __FUNCTION__, type, ap->ssid, is_in_anim, cur_btn, btn); */
        if(NULL == cur_ap) {
            cur_ap = (hal_wlan_ap_t *)Hal_Mem_Alloc(sizeof(hal_wlan_ap_t));
        }
        Hal_Mem_Copy(cur_ap, ap, sizeof(hal_wlan_ap_t));
        lv_watch_set_free_ptr(first_child, cur_ap);
    } else {
        /* printf("%s: type %d, anim %d, cur_btn %p, btn %p\n", */
        /*        __FUNCTION__, type, is_in_anim, cur_btn, btn); */
        if(cur_ap) {
            Hal_Mem_Free(cur_ap);
            lv_watch_set_free_ptr(first_child, NULL);
        }
    }

    lv_obj_t * label2 = NULL;
    if(is_multi_label) {
        if(cur_btn) {
            label2 = lv_obj_get_child_back(label_cont, label1);
        } else {
            label2 = lv_label_create(label_cont, NULL);
            lv_obj_add_style(label2, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_SMALL_GRAY);
            lv_label_set_long_mode(label2, LV_LABEL_LONG_SROLL_CIRC);
        }
        if(WLAN_BTN_TYPE_OPENING == type) {
            lv_label_set_text_id(label2, WATCH_TEXT_ID_CONNECTION);
        } else if(WLAN_BTN_TYPE_GETTING_IP == type) {
            lv_label_set_text_id(label2, WATCH_TEXT_ID_GETTING_IP);
        } else if(WLAN_BTN_TYPE_ACT == type) {
            lv_label_set_text_id(label2, WATCH_TEXT_ID_CONNECTED);
        } else if(WLAN_BTN_TYPE_NO_INTERNET == type) {
            lv_label_set_text_id(label2, WATCH_TEXT_ID_NO_INTERNET);
        } else if(WLAN_BTN_TYPE_SAVED == type) {
            lv_label_set_text_id(label2, WATCH_TEXT_ID_SAVED);
        } else if(WLAN_BTN_TYPE_PASSWORD_ERROR == type) {
            lv_label_set_text_id(label2, WATCH_TEXT_ID_PASSWORD_ERROR);
        } else {
            lv_label_set_text_id(label2, WATCH_TEXT_ID_CONNECT_FAILED);
        }
    }

    if((WLAN_BTN_TYPE_REFRESH == type) || (WLAN_BTN_TYPE_REFRESHING == type)) {
        lv_obj_t * img_cont;
        if(cur_btn) {
            img_cont = lv_obj_get_child(btn, NULL);
        } else {
            img_cont = lv_cont_create(btn, NULL);
            lv_obj_set_click(img_cont, false);
            lv_obj_set_size(img_cont, font_h + 2, font_h + 2);
            lv_obj_add_style(img_cont, LV_CONT_PART_MAIN, &lv_style_pretty);
            lv_obj_set_style_local_bg_opa(img_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
            lv_obj_set_style_local_bg_color(img_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT,
                                            LV_COLOR_MAKE(0x6b, 0x9a, 0xc7));
            lv_obj_set_style_local_bg_grad_color(img_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT,
                                                 LV_COLOR_MAKE(0x2b, 0x59, 0x8b));
            ext->refresh_img = lv_img_create(img_cont, NULL);
        }
        if(WLAN_BTN_TYPE_REFRESHING == type) {
            if(false == is_in_anim) {
                lv_obj_set_click(btn, false);
                wlan_play_refreshing_anim(ext->refresh_img);
            }
        } else {
            if(is_in_anim) {
                lv_anim_del(ext->refresh_img, NULL);
            }
            if(is_in_anim || (NULL == cur_btn)) {
                lv_img_set_src(ext->refresh_img, ICON_SETTING_REFRESH_1);
                lv_obj_set_click(btn, true);
            }
        }
        if(NULL == cur_btn) {
            lv_obj_align(ext->refresh_img, img_cont, LV_ALIGN_CENTER, 0, 0);
        }

        lv_obj_set_width(label1,
                         btn_w - pad_top - pad_bottom - pad_inner - lv_obj_get_width(img_cont));
    } else {
        lv_obj_t * lock_img;
        lv_obj_t * signal_img;
        if(cur_btn) {
            signal_img = lv_obj_get_child(btn, NULL);
            lock_img = lv_obj_get_child(btn, signal_img);
        } else {
            lock_img = lv_img_create(btn, NULL);
            lv_img_set_src(lock_img, ICON_SETTING_LOCK);
            lv_img_set_auto_size(lock_img, false);

            signal_img = lv_img_create(btn, NULL);
        }
        if((WLAN_BTN_TYPE_OPENING == type)
           || (WLAN_BTN_TYPE_GETTING_IP == type)) {
            if(false == is_in_anim) {
                wlan_play_refreshing_anim(signal_img);
            }
        } else {
            if(is_in_anim) {
                lv_anim_del(signal_img, NULL);
            }
            lv_img_set_src(signal_img, wlan_get_signal_src(hal_wlan_rssi_level_calc(ap->power)));
        }

        lv_coord_t label_w = btn_w - pad_top - pad_bottom - 2 * pad_inner -
            lv_obj_get_width(lock_img) - lv_obj_get_width(signal_img);
        lv_obj_set_width(label1, label_w);
        if(label2) {
            lv_obj_set_width(label2, label_w);
        }

        if(HAL_WLAN_SECURITY_OPEN == ap->security) {
            lv_obj_set_style_local_image_opa(lock_img, LV_IMG_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0);
        } else {
            lv_obj_set_style_local_image_opa(lock_img, LV_IMG_PART_MAIN, LV_STATE_DEFAULT,
                                             LV_OPA_COVER);
        }
    }

    return btn;
}

static void wlan_sw_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_ext_t * ext = wlan_get_ext(ACT_ID_WLAN);
    if(NULL == ext) return;

    if(lv_switch_get_state(ext->sw)) {
        if(hal_wlan_ui_close_wlan()) {
            lv_obj_set_click(btn, false); // set true when the wlan is closed
            wlan_rm_ap_list_btn(ext);
            wlan_add_note_label(&ext->note_label, lv_obj_get_parent(ext->list),
                                WATCH_TEXT_ID_WLAN_CLOSING);
        }
    } else {
        if(hal_wlan_ui_open_wlan()) {
            lv_obj_set_click(btn, false); // set true when the wlan is opened
            wlan_add_note_label(&ext->note_label, lv_obj_get_parent(ext->list),
                                WATCH_TEXT_ID_WLAN_OPENING);
        }
    }
}

static void wlan_add_btn_switch(wlan_ext_t * ext, hal_wlan_info_t * wlan_info)
{
    lv_obj_t * btn = lv_btn_create(ext->list, NULL);
    lv_obj_add_style(btn, LV_BTN_PART_MAIN, &ext->btn_style);
    lv_coord_t font_h = lv_font_get_line_height(WLAN_DEF_FONT);
    lv_coord_t btn_w = lv_obj_get_width(ext->list);
    lv_obj_set_size(btn, btn_w, font_h + 10);
    lv_btn_set_layout(btn, LV_LAYOUT_ROW_MID);
    lv_obj_set_event_cb(btn, wlan_sw_btn_event_cb);
    lv_page_glue_obj(btn, true);
    lv_watch_obj_add_element(btn);
    printf("%s: btn %p\n", __FUNCTION__, btn);

    lv_coord_t sw_w = font_h * 3 / 2;
    lv_coord_t pad_left = lv_obj_get_style_pad_left(btn, LV_BTN_PART_MAIN);
    lv_coord_t pad_right = lv_obj_get_style_pad_right(btn, LV_BTN_PART_MAIN);
    lv_coord_t pad_inner = lv_obj_get_style_pad_inner(btn, LV_BTN_PART_MAIN);

    ext->sw_label = lv_label_create(btn, NULL);
    lv_label_set_long_mode(ext->sw_label, LV_LABEL_LONG_SROLL_CIRC);
    lv_obj_set_width(ext->sw_label, btn_w - pad_left - pad_right - pad_inner - sw_w);
    lv_obj_add_style(ext->sw_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);

    ext->sw = lv_switch_create(btn, NULL);
    wlan_set_sw_style(ext->sw);
    lv_obj_set_size(ext->sw, sw_w, font_h * 2 / 3);
    lv_obj_set_click(ext->sw, false);

    if(!wlan_info) {
        lv_label_set_text_id(ext->sw_label, WATCH_TEXT_ID_WLAN_OFF);
    } else if(HAL_WLAN_STATE_INIT == wlan_info->state) {
        lv_label_set_text_id(ext->sw_label, WATCH_TEXT_ID_WLAN_OFF);
        lv_obj_set_click(btn, false); // set true when the wlan is opened
    } else {
        lv_label_set_text_id(ext->sw_label, WATCH_TEXT_ID_WLAN_ON);
        lv_switch_on(ext->sw, false);
        if(HAL_WLAN_STATE_DEINIT == wlan_info->state) {
            lv_obj_set_click(btn, false); // set true when the wlan is closed
        }
    }
}

static void wlan_add_btn_ap_list(wlan_ext_t * ext, hal_wlan_info_t * wlan_info)
{
    if((NULL == ext) || (NULL == wlan_info)) {
        printf("%s: warning, NULL pointer, ext %p, wlan_info %p\n", __FUNCTION__, ext, wlan_info);
        return;
    }

    if(wlan_info->proc.ap) {
        printf("%s: state %d, is hid %d, ap state %d, ssid %s\n",
               __FUNCTION__, wlan_info->state, wlan_info->proc.ap->is_hidden,
               wlan_info->proc.ap->state, wlan_info->proc.ap->nw->ssid);
    } else {
        printf("%s: state %d\n", __FUNCTION__, wlan_info->state);
    }

    lv_obj_t * scrl = lv_page_get_scrollable(ext->list);
    lv_obj_t * old_btn = lv_obj_get_parent(ext->sw);
    lv_obj_t * btn = lv_obj_get_child_back(scrl, old_btn);
    lv_obj_t * refresh_btn = NULL;
    if(ext->refresh_img) {
        refresh_btn = lv_obj_get_parent(lv_obj_get_parent(ext->refresh_img));
    }

    bool refresh_scrl = false;

    hal_wlan_saved_ap_t * proc_ap = NULL;
    if(wlan_info->proc.ap
       && ((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_OPENING == wlan_info->proc.proc_state))) {
        if((HAL_WLAN_STATE_OPEN_AUTO == wlan_info->state)
           && (wlan_info->proc.ap->is_hidden
               || (HAL_WLAN_AP_STATE_RETRY == wlan_info->proc.ap->state))) {
            printf("%s: not display hidden or retrying ap\n", __FUNCTION__);
        } else {
            proc_ap = wlan_info->proc.ap;
            WLAN_BTN_TYPE_T btn_type = WLAN_BTN_TYPE_ACT;
            if(HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state) {
                btn_type = WLAN_BTN_TYPE_NO_INTERNET;
            } else if(HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.proc_state) {
                btn_type = WLAN_BTN_TYPE_GETTING_IP;
            } else if(HAL_WLAN_AP_STATE_OPENING == wlan_info->proc.proc_state) {
                btn_type = WLAN_BTN_TYPE_OPENING;
            }
            hal_wlan_ap_t ap = {};
            Hal_Mem_Copy(ap.ssid, proc_ap->nw->ssid, HAL_WLAN_MAX_SSID_LEN + 1);
            ap.security = proc_ap->nw->security;
            ap.power = proc_ap->power;
            if(refresh_btn == btn) {
                btn = wlan_add_btn(ext, NULL, btn_type, &ap);
                _lv_ll_move_before(&scrl->child_ll, btn, old_btn);
                refresh_scrl = true;
            } else {
                wlan_add_btn(ext, btn, btn_type, &ap);
            }
            old_btn = btn;
            btn = lv_obj_get_child_back(scrl, old_btn);
        }
    }

    hal_wlan_saved_ap_t * node = _lv_ll_get_head(&wlan_info->saved_ap_list);
    while(node) {
        if(0 == node->power) {
            // invalid ap
            break;
        }

        if((proc_ap != node) && (false == node->is_hidden)) {
            WLAN_BTN_TYPE_T btn_type = WLAN_BTN_TYPE_SAVED;
            if(HAL_WLAN_AP_STATE_OPEN_FAILED == node->state) {
                btn_type = WLAN_BTN_TYPE_OPEN_FAIL;
            } else if(HAL_WLAN_AP_STATE_PASSWORD_ERROR == node->state) {
                btn_type = WLAN_BTN_TYPE_PASSWORD_ERROR;
            }
            hal_wlan_ap_t ap = {};
            Hal_Mem_Copy(ap.ssid, node->nw->ssid, HAL_WLAN_MAX_SSID_LEN + 1);
            ap.security = node->nw->security;
            ap.power = node->power;
            if(refresh_btn == btn) {
                btn = wlan_add_btn(ext, NULL, btn_type, &ap);
                _lv_ll_move_before(&scrl->child_ll, btn, old_btn);
                refresh_scrl = true;
            } else {
                wlan_add_btn(ext, btn, btn_type, &ap);
            }
            old_btn = btn;
            btn = lv_obj_get_child_back(scrl, old_btn);
        } else {
            printf("%s: not display ssid %s\n", __FUNCTION__, node->nw->ssid);
        }

        node = _lv_ll_get_next(&wlan_info->saved_ap_list, node);
    }

    if(refresh_btn && (refresh_btn != btn)) {
        while(btn) {
            old_btn = btn;
            btn = lv_obj_get_child_back(scrl, btn);
            void * ptr = lv_watch_get_free_ptr(lv_obj_get_child_back(old_btn, NULL));
            if(ptr) {
                Hal_Mem_Free(ptr);
            }
            lv_obj_del(old_btn);
            refresh_scrl = false;
            if(refresh_btn == btn) {
                break;
            }
        }
    }

    if((HAL_WLAN_STATE_SCAN == wlan_info->state)
       || (HAL_WLAN_STATE_SCAN == wlan_info->next_state)) { // refreshing
        if(NULL == refresh_btn) {
            refresh_btn = wlan_add_btn(ext, NULL, WLAN_BTN_TYPE_REFRESHING, NULL);
        } else {
            wlan_add_btn(ext, refresh_btn, WLAN_BTN_TYPE_REFRESHING, NULL);
        }
    } else {
        if(NULL == refresh_btn) {
            refresh_btn = wlan_add_btn(ext, NULL, WLAN_BTN_TYPE_REFRESH, NULL);
        } else {
            wlan_add_btn(ext, refresh_btn, WLAN_BTN_TYPE_REFRESH, NULL);
        }
    }

    btn = lv_obj_get_child_back(scrl, refresh_btn);
    hal_wlan_ap_t * ap = _lv_ll_get_head(&wlan_info->scan_list);
    while(ap) {
        if(NULL == btn) {
            btn = wlan_add_btn(ext, NULL, WLAN_BTN_TYPE_SCAN_LIST, ap);
        } else {
            wlan_add_btn(ext, btn, WLAN_BTN_TYPE_SCAN_LIST, ap);
        }
        btn = lv_obj_get_child_back(scrl, btn);
        ap = _lv_ll_get_next(&wlan_info->scan_list, ap);
    }

    while(btn) {
        old_btn = btn;
        btn = lv_obj_get_child_back(scrl, btn);
        void * ptr = lv_watch_get_free_ptr(lv_obj_get_child_back(old_btn, NULL));
        if(ptr) {
            Hal_Mem_Free(ptr);
        }
        lv_obj_del(old_btn);
        refresh_scrl = false;
    }

    if(refresh_scrl) {
        scrl->signal_cb(scrl, LV_SIGNAL_CHILD_CHG, NULL);
    }
}

static bool wlan_pwd_error_connect_btn_event_cb(lv_obj_t * btn)
{
    wlan_login_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_DIALOG);
    if(NULL == ext) {
        printf("%s: warning, not find wlan dialog\n", __FUNCTION__);
        return true;
    }

    printf("%s: pwd %s\n", __FUNCTION__, ext->pwd);
    if(wlan_check_pwd_len(ext->ap.security, ext->pwd)) {
        hal_wlan_ui_open_ap(ext->ap.ssid, ext->ap.security, ext->pwd);

        return true;
    }

    return false;
}

#if USE_LV_WATCH_KEYPAD != 0
static void wlan_pwd_error_get_pwd(char * text)
{
    wlan_login_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_DIALOG);
    if(NULL == ext) {
        printf("%s: warning, not find wlan dialog\n", __FUNCTION__);
        return;
    }

    wlan_get_pwd_handle(text, ext->ap.ssid, ext->ap.security, &ext->pwd,
                        ext->pwd_label, ext->connect_btn);
}

static void wlan_pwd_error_pwd_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) return;

    wlan_login_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_DIALOG);
    if(NULL == ext) {
        printf("%s: warning, not find wlan dialog\n", __FUNCTION__);
        return;
    }

    keypad_para_t param;
    param.text = ext->pwd;
    param.password_mode = true;
    param.max_length = HAL_WLAN_MAX_PWD_LEN;
    param.min_length = hal_wlan_get_min_pwd_len(ext->ap.security);
    param.func = wlan_pwd_error_get_pwd;
    keypad_create_btn_action(&param);
}
#endif

static void wlan_dialog_prepare_destory(lv_obj_t * activity_obj)
{
    printf("%s\n", __FUNCTION__);

    wlan_login_ext_t * ext = wlan_get_ext(ACT_ID_WLAN_DIALOG);
    if(NULL == ext) {
        printf("%s: error, ui lost!\n", __FUNCTION__);
        return;
    }

    if(ext->pwd) {
        Hal_Mem_Free(ext->pwd);
    }

    lv_watch_png_cache_all_free();
}

static void wlan_pwd_error_create(hal_wlan_ap_t * ap)
{
    lv_watch_activity_ext_t activity_ext;
    memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
    activity_ext.actId = ACT_ID_WLAN_DIALOG;
    activity_ext.create = NULL;
    activity_ext.prepare_destory = wlan_dialog_prepare_destory;
    lv_obj_t * activity_obj = lv_watch_creat_activity_obj(&activity_ext);
    LV_ASSERT_MEM(activity_obj);

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    wlan_login_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(wlan_login_ext_t));
    LV_ASSERT_MEM(ext);

    ext->pwd = NULL;
    Hal_Mem_Copy(&ext->ap, ap, sizeof(hal_wlan_ap_t));
    printf("%s: ap %s\n", __FUNCTION__, ap->ssid);

    lv_obj_t * content = wlan_dialog_create(obj, ACT_ID_WLAN_DIALOG, false,
                                            wlan_pwd_error_connect_btn_event_cb);

    lv_obj_t * cont = lv_obj_get_parent(content);

    lv_obj_t * title_label = lv_obj_get_child_back(cont, NULL);
    lv_label_set_text(title_label, ap->ssid);

    ext->connect_btn = wlan_dialog_get_ok_btn(content);
    lv_obj_t * connect_label = lv_obj_get_child(ext->connect_btn, NULL);
    if(HAL_WLAN_SECURITY_OPEN != ap->security) {
        lv_obj_set_style_local_text_color(connect_label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT,
                                          LV_COLOR_GRAY);
    }
    lv_label_set_text_id(connect_label, WATCH_TEXT_ID_CONNECT);
    lv_obj_align(connect_label, ext->connect_btn, LV_ALIGN_CENTER, 0, 0);

    lv_obj_t * label = lv_label_create(content, NULL);
    lv_obj_set_style_local_text_color(label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT,
                                      LV_COLOR_MAKE(255, 80, 80));
    lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
    lv_label_set_long_mode(label, LV_LABEL_LONG_BREAK);
    lv_obj_set_width(label, lv_obj_get_width_fit(content) - 20);
    lv_label_set_text_id(label, WATCH_TEXT_ID_PWD_ERR_AND_RETRY);
    lv_obj_align(label, content, LV_ALIGN_IN_TOP_MID, 0, 0);

#if USE_LV_WATCH_KEYPAD != 0
    if((HAL_WLAN_SECURITY_OPEN != ap->security)
       && (HAL_WLAN_SECURITY_MAX > ap->security)) {
        lv_obj_t * pwd_btn = lv_btn_create(content, NULL);
        lv_coord_t hor = lv_obj_get_width(cont) - lv_obj_get_x(ext->connect_btn) -
            lv_obj_get_width(ext->connect_btn);
        lv_obj_set_size(pwd_btn, lv_obj_get_width_fit(content) - 2 * hor,
                        lv_obj_get_height(title_label) + 10);
        wlan_btn_set_input_style(pwd_btn);
        lv_obj_set_event_cb(pwd_btn, wlan_pwd_error_pwd_btn_event_cb);
        lv_obj_align(pwd_btn, label, LV_ALIGN_OUT_BOTTOM_MID, 0,
                     lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN));

        ext->pwd_label = lv_label_create(pwd_btn, NULL);
        lv_obj_add_style(ext->pwd_label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT_GRAY);
        lv_label_set_long_mode(ext->pwd_label, LV_LABEL_LONG_SROLL_CIRC);
        lv_obj_set_width(ext->pwd_label, lv_obj_get_width(pwd_btn) - 10);
        lv_label_set_text_id(ext->pwd_label, WATCH_TEXT_ID_PASSWORD);
        lv_obj_align(ext->pwd_label, pwd_btn, LV_ALIGN_CENTER, 0, 0);
    }
#endif

    wlan_dialog_anim_start(cont);
}

static bool wlan_is_closing_wlan(lv_obj_t * sw)
{
    if((false == lv_obj_get_click(lv_obj_get_parent(sw)))
       && lv_switch_get_state(sw)) {
        printf("%s: closing wlan\n", __FUNCTION__);
        return true;
    }

    return false;
}

static void wlan_update_ap_list_task_cb(lv_task_t * task)
{
    wlan_ext_t * ext = wlan_get_ext(ACT_ID_WLAN);
    if(NULL == ext) return;

    printf("%s\n", __FUNCTION__);

    hal_wlan_info_t * wlan_info = hal_wlan_get_info();
    if(!wlan_info
       || (HAL_WLAN_STATE_INIT == wlan_info->state)
       || (HAL_WLAN_STATE_DEINIT == wlan_info->state)) {
        printf("%s: warning, wlan is not opened\n", __FUNCTION__);
        return;
    }

    if(wlan_is_closing_wlan(ext->sw)) {
        return;
    }

    wlan_add_btn_ap_list(ext, wlan_info);
    if(wlan_info
       && ((HAL_WLAN_STATE_OPEN_SPEC == wlan_info->state)
           || (HAL_WLAN_STATE_OPEN_SPEC == wlan_info->next_state))) {
        lv_page_focus(ext->list, lv_obj_get_parent(ext->sw), false);
    }
}

static void wlan_closed_task_cb(lv_task_t * task)
{
    wlan_ext_t * ext = wlan_get_ext(ACT_ID_WLAN);
    if(NULL == ext) {
        printf("%s: no wlan ui\n", __FUNCTION__);
        return;
    }

    lv_switch_off(ext->sw, false);
    lv_obj_set_click(lv_obj_get_parent(ext->sw), true);
    wlan_rm_ap_list_btn(ext);
    wlan_add_note_label(&ext->note_label, lv_obj_get_parent(ext->list),
                        WATCH_TEXT_ID_WLAN_NOTE);
}

static void wlan_open_failed_task_cb(lv_task_t * task)
{
    wlan_ext_t * ext = wlan_get_ext(ACT_ID_WLAN);
    if(NULL == ext) {
        printf("%s: no wlan ui\n", __FUNCTION__);
        return;
    }

    lv_obj_set_click(lv_obj_get_parent(ext->sw), true);
    wlan_add_note_label(&ext->note_label, lv_obj_get_parent(ext->list),
                        WATCH_TEXT_ID_OPEN_FAILED);
}

static void wlan_start_scan_task_cb(lv_task_t * task)
{
    wlan_ext_t * ext = wlan_get_ext(ACT_ID_WLAN);
    if(NULL == ext) return;

    if(NULL == ext->refresh_img) {
        printf("%s: warning, refresh img is NULL\n", __FUNCTION__);
        return;
    }

    if(wlan_is_closing_wlan(ext->sw)) {
        return;
    }

    printf("%s\n", __FUNCTION__);

    lv_obj_t * btn = lv_obj_get_parent(lv_obj_get_parent(ext->refresh_img));
    if(WLAN_BTN_TYPE_REFRESH == lv_watch_get_free_num(btn)) {
        wlan_play_refreshing_anim(ext->refresh_img);
        lv_watch_set_free_num(btn, WLAN_BTN_TYPE_REFRESHING);
    }
}

static void wlan_stop_scan_task_cb(lv_task_t * task)
{
    wlan_ext_t * ext = wlan_get_ext(ACT_ID_WLAN);
    if(NULL == ext) return;

    if(NULL == ext->refresh_img) {
        printf("%s: warning, refresh img is NULL\n", __FUNCTION__);
        return;
    }

    if(wlan_is_closing_wlan(ext->sw)) {
        return;
    }

    printf("%s\n", __FUNCTION__);

    lv_obj_t * btn = lv_obj_get_parent(lv_obj_get_parent(ext->refresh_img));
    if(WLAN_BTN_TYPE_REFRESHING == lv_watch_get_free_num(btn)) {
        lv_anim_del(ext->refresh_img, NULL);
        lv_img_set_src(ext->refresh_img, ICON_SETTING_REFRESH_1);
        lv_obj_set_click(lv_obj_get_parent(lv_obj_get_parent(ext->refresh_img)), true);
        lv_watch_set_free_num(btn, WLAN_BTN_TYPE_REFRESH);
    }
}

static void wlan_update_act_ap_rssi_task_cb(lv_task_t * task)
{
    wlan_ext_t * ext = wlan_get_ext(ACT_ID_WLAN);
    if(NULL == ext) return;

    if(wlan_is_closing_wlan(ext->sw)) {
        return;
    }

    lv_obj_t * btn = lv_obj_get_child_back(lv_page_get_scrl(ext->list), lv_obj_get_parent(ext->sw));
    if(NULL == btn) {
        printf("%s: warning, act ap is absent\n", __FUNCTION__);
        return;
    }

    lv_obj_t * signal_img = lv_obj_get_child(btn, NULL);
    lv_img_set_src(signal_img, wlan_get_signal_src(hal_wlan_get_rssi_level()));
}

static void wlan_opened_task_cb(lv_task_t * task)
{
    wlan_ext_t * ext = wlan_get_ext(ACT_ID_WLAN);
    if(NULL == ext) return;

    hal_wlan_info_t * wlan_info = hal_wlan_get_info();
    if(!wlan_info || (HAL_WLAN_STATE_INIT == wlan_info->state)) {
        printf("%s: warning, wlan is not opened\n", __FUNCTION__);
        return;
    }

    printf("%s: wlan state %d\n", __FUNCTION__, wlan_info->state);

    lv_obj_set_click(lv_obj_get_parent(ext->sw), true);
    lv_switch_on(ext->sw, false);
    lv_label_set_text_id(ext->sw_label, WATCH_TEXT_ID_WLAN_ON);
    lv_obj_del(ext->note_label);
    ext->note_label = NULL;
    wlan_add_btn_ap_list(ext, wlan_info);

    lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_WLAN_OPTION);
    if(NULL == activity_obj) {
        return;
    }
    lv_obj_t * obj = NULL;
    lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &obj);
    if(NULL == obj) {
        return;
    }
    lv_obj_t * list = lv_obj_get_child(lv_obj_get_child(obj, NULL), NULL);
    lv_obj_t * scrl = lv_page_get_scrollable(list);
    lv_obj_t * saved_ap_btn = lv_obj_get_child_back(scrl, NULL);
    if(NULL == lv_obj_get_child_back(scrl, saved_ap_btn)) {
        wlan_option_add_btn(list, saved_ap_btn);
    }
}

static void wlan_getting_ip_task_cb(lv_task_t * task)
{
    wlan_ext_t * ext = wlan_get_ext(ACT_ID_WLAN);
    if(NULL == ext) return;

    if(wlan_is_closing_wlan(ext->sw)) {
        return;
    }

    lv_obj_t * act_btn = lv_obj_get_child_back(lv_page_get_scrollable(ext->list),
                                               lv_obj_get_parent(ext->sw));
    if(act_btn) {
        lv_obj_t * cont = lv_obj_get_child_back(act_btn, NULL);
        lv_obj_t * label = lv_obj_get_child(cont, NULL);
        if(WATCH_TEXT_ID_OPENING == label->user_data.user_num) {
            printf("%s: opening ap has been displayed\n", __FUNCTION__);
            lv_label_set_text_id(label, WATCH_TEXT_ID_GETTING_IP);
            return;
        }
    }

    printf("%s: opening ap has not been displayed\n", __FUNCTION__);
    wlan_add_btn_ap_list(ext, hal_wlan_get_info());
}

static void wlan_pwd_error_task_cb(lv_task_t * task)
{
    wlan_ext_t * ext = wlan_get_ext(ACT_ID_WLAN);
    if(NULL == ext) return;

    if(wlan_is_closing_wlan(ext->sw)) {
        return;
    }

    lv_obj_t * top_act_obj = lv_watch_get_top_activity_obj();
    lv_watch_activity_ext_t * top_ext = lv_obj_get_ext_attr(top_act_obj);
    if(top_ext
       && (ACT_ID_WLAN <= top_ext->actId)
       && (ACT_ID_WLAN_SAVED_AP >= top_ext->actId)) {
        lv_obj_t * sw_btn = lv_obj_get_parent(ext->sw);
        lv_obj_t * btn = lv_obj_get_child_back(lv_obj_get_parent(sw_btn), sw_btn);
        hal_wlan_ap_t * ap = lv_watch_get_free_ptr(lv_obj_get_child_back(btn, NULL));
        wlan_pwd_error_create(ap);
    }
}

static void wlan_event_cb(HAL_WLAN_EVENT_T event)
{
    if(lv_watch_get_activity_obj(ACT_ID_WLAN) && (true == watch_get_lcd_status())) {
        lv_task_t * task = NULL;
        uint32_t period = 10000;
        if(HAL_WLAN_EVENT_UPDATE_AP_LIST == event) {
            task = lv_task_create(wlan_update_ap_list_task_cb, period, LV_TASK_PRIO_HIGH, NULL);
        } else if(HAL_WLAN_EVENT_WLAN_CLOSED == event) {
            task = lv_task_create(wlan_closed_task_cb, period, LV_TASK_PRIO_HIGH, NULL);
        } else if(HAL_WLAN_EVENT_OPEN_WLAN_FAILURE == event) {
            task = lv_task_create(wlan_open_failed_task_cb, period, LV_TASK_PRIO_HIGH, NULL);
        } else if(HAL_WLAN_EVENT_START_SCAN == event) {
            task = lv_task_create(wlan_start_scan_task_cb, period, LV_TASK_PRIO_HIGH, NULL);
        } else if(HAL_WLAN_EVENT_STOP_SCAN_ABNORMAL == event) {
            task = lv_task_create(wlan_stop_scan_task_cb, period, LV_TASK_PRIO_HIGH, NULL);
        } else if(HAL_WLAN_EVENT_UPDATE_ACT_AP_RSSI == event) {
            task = lv_task_create(wlan_update_act_ap_rssi_task_cb, period, LV_TASK_PRIO_HIGH, NULL);
        } else if(HAL_WLAN_EVENT_WLAN_OPENED == event) {
            task = lv_task_create(wlan_opened_task_cb, period, LV_TASK_PRIO_HIGH, NULL);
        } else if(HAL_WLAN_EVENT_GETTING_IP == event) {
            task = lv_task_create(wlan_getting_ip_task_cb, period, LV_TASK_PRIO_HIGH, NULL);
        } else if(HAL_WLAN_EVENT_OPEN_FAILED_WITH_PASSWORD_ERROR == event) {
            task = lv_task_create(wlan_pwd_error_task_cb, period, LV_TASK_PRIO_HIGHEST, NULL);
        }
        if(task) {
            lv_task_once(task);
            lv_task_set_period(task, 10);
        }
    }
}

static void wlan_add_note_label(lv_obj_t ** note_label, lv_obj_t * par, uint16_t txt_id)
{
    printf("%s: txt id %d, note label %p\n", __FUNCTION__, txt_id, note_label);
    lv_obj_t * label = *note_label;
    if(NULL == label) {
        label = lv_label_create(par, NULL);
        lv_obj_add_style(label, LV_LABEL_PART_MAIN, WLAN_STYLE_FONT);
        lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
        lv_label_set_long_mode(label, LV_LABEL_LONG_BREAK);
        lv_obj_set_width(label, lv_obj_get_width(par) - 40);
        *note_label = label;
    }
    lv_label_set_text_id(label, txt_id);
    lv_obj_align(label, par, LV_ALIGN_CENTER, 0, 20);
}

static void wlan_prepare_destory(lv_obj_t * activity_obj)
{
    printf("%s\n", __FUNCTION__);
    lv_watch_png_cache_all_free();

    wlan_ext_t * ext = (wlan_ext_t *)wlan_get_ext(ACT_ID_WLAN);
    if(NULL == ext) return;
    wlan_rm_ap_list_btn(ext);
    lv_style_reset(&ext->btn_style);

    hal_wlan_ui_state_chg(false);
}

static lv_obj_t * wlan_create(lv_obj_t * activity_obj)
{
    hal_wlan_ui_state_chg(true);

    if(NULL == activity_obj) {
        lv_watch_activity_ext_t activity_ext;
        memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
        activity_ext.actId = ACT_ID_WLAN;
        activity_ext.create = wlan_create;
        activity_ext.prepare_destory = wlan_prepare_destory;
        activity_obj = lv_watch_creat_activity_obj(&activity_ext);
        LV_ASSERT_MEM(activity_obj);
    }

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    wlan_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(wlan_ext_t));
    LV_ASSERT_MEM(ext);

    ext->note_label = NULL;

    lv_obj_t * cont = wlan_add_bg(obj);

    lv_obj_t * title_cont = wlan_add_title(cont, WATCH_TEXT_ID_WLAN);

    lv_style_init(&ext->btn_style);
    lv_style_copy(&ext->btn_style, &lv_watch_style_transp);
    lv_style_set_pad_top(&ext->btn_style, LV_STATE_DEFAULT, 4);
    lv_style_set_pad_bottom(&ext->btn_style, LV_STATE_DEFAULT, 4);
    lv_style_set_pad_left(&ext->btn_style, LV_STATE_DEFAULT, 5);
    lv_style_set_pad_right(&ext->btn_style, LV_STATE_DEFAULT, 5);
    lv_style_set_pad_inner(&ext->btn_style, LV_STATE_DEFAULT, 2);
    lv_style_set_pad_top(&ext->btn_style, LV_STATE_PRESSED, 4);
    lv_style_set_pad_bottom(&ext->btn_style, LV_STATE_PRESSED, 4);
    lv_style_set_pad_left(&ext->btn_style, LV_STATE_PRESSED, 5);
    lv_style_set_pad_right(&ext->btn_style, LV_STATE_PRESSED, 5);
    lv_style_set_pad_inner(&ext->btn_style, LV_STATE_PRESSED, 2);
    lv_style_set_bg_color(&ext->btn_style, LV_STATE_PRESSED, LV_COLOR_WHITE);
    lv_style_set_bg_grad_color(&ext->btn_style, LV_STATE_PRESSED, LV_COLOR_MAKE(0x10, 0x26, 0x3c));
    lv_style_set_bg_grad_dir(&ext->btn_style, LV_STATE_PRESSED, LV_GRAD_DIR_VER);
    lv_style_set_bg_opa(&ext->btn_style, LV_STATE_PRESSED, LV_OPA_20);
    lv_style_set_radius(&ext->btn_style, LV_STATE_PRESSED, 10);

    lv_obj_t * option_btn = lv_btn_create(cont, NULL);
    lv_obj_set_size(option_btn, 50, 40);
    lv_obj_add_style(option_btn, LV_BTN_PART_MAIN, &lv_style_transp_tight);
    lv_obj_set_style_local_bg_color(option_btn, LV_BTN_PART_MAIN, LV_STATE_PRESSED, LV_COLOR_WHITE);
    lv_obj_set_style_local_bg_opa(option_btn, LV_BTN_PART_MAIN, LV_STATE_PRESSED, LV_OPA_20);
    lv_obj_set_style_local_radius(option_btn, LV_BTN_PART_MAIN, LV_STATE_PRESSED, 15);
    lv_obj_set_event_cb(option_btn, wlan_option_btn_event_cb);
    if(LV_BIDI_DIR_RTL == lv_obj_get_base_dir(cont)) {
        lv_obj_align(option_btn, cont, LV_ALIGN_IN_TOP_LEFT, 4, 4);
    } else {
        lv_obj_align(option_btn, cont, LV_ALIGN_IN_TOP_RIGHT, -4, 4);
    }

    lv_obj_t * option_img = lv_img_create(option_btn, NULL);
    lv_img_set_auto_size(option_img, true);
    lv_img_set_src(option_img, ICON_SETTING_OPTION);
    lv_obj_align(option_img, option_btn, LV_ALIGN_CENTER, 0, 0);

    ext->list = lv_list_create(cont, NULL);
    wlan_list_set_common_param(ext->list);
    lv_obj_set_size(ext->list,
                    lv_obj_get_width_fit(cont),
                    lv_obj_get_height(cont) - lv_obj_get_y(title_cont)
                    - lv_obj_get_height(title_cont) - 4);
    lv_obj_align(ext->list, cont, LV_ALIGN_IN_BOTTOM_MID, 0, -2);

    ext->refresh_img = NULL;
    hal_wlan_info_t * wlan_info = hal_wlan_get_info();
    wlan_add_btn_switch(ext, wlan_info);
    if(!wlan_info) {
        wlan_add_note_label(&ext->note_label, cont, WATCH_TEXT_ID_WLAN_NOTE);
    } else if(HAL_WLAN_STATE_INIT == wlan_info->state) {
        wlan_add_note_label(&ext->note_label, cont, WATCH_TEXT_ID_WLAN_OPENING);
    } else if(HAL_WLAN_STATE_DEINIT == wlan_info->state) {
        wlan_add_note_label(&ext->note_label, cont, WATCH_TEXT_ID_WLAN_CLOSING);
    } else {
        wlan_add_btn_ap_list(ext, wlan_info);
    }

    return obj;
}

#endif /* WLAN_MANUAL_SET_WIFI_SUPP */

#endif /* USE_LV_WATCH_WLAN */
